//Servicio de STAT. bool_t stat_rpc_1_svc(char* byte, struct server_stat *data_out, struct svc_req *rqstp) { //Petición de estadísticas. struct sockaddr_in *client_addr = svc_getcaller(rqstp->rq_xprt); printf("s> %s:%d init stat\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); //Respuesta. pthread_mutex_lock(&stats_mutex[0]); data_out->ping = htonl(stats[0]); pthread_mutex_unlock(&stats_mutex[0]); pthread_mutex_lock(&stats_mutex[1]); data_out->swap = htonl(stats[1]); pthread_mutex_unlock(&stats_mutex[1]); pthread_mutex_lock(&stats_mutex[2]); data_out->hash = htonl(stats[2]); pthread_mutex_unlock(&stats_mutex[2]); pthread_mutex_lock(&stats_mutex[3]); data_out->check = htonl(stats[3]); pthread_mutex_unlock(&stats_mutex[3]); pthread_mutex_lock(&stats_mutex[4]); data_out->stat = htonl(stats[4]); pthread_mutex_unlock(&stats_mutex[4]); //Resultado de stat. printf("s> %s:%d stat = %u %u %u %u %u\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), ntohl(data_out->ping), ntohl(data_out->swap), ntohl(data_out->hash), ntohl(data_out->check), ntohl(data_out->stat)); //Contador de estadísticas. pthread_mutex_lock(&stats_mutex[4]); stats[4]++; pthread_mutex_unlock(&stats_mutex[4]); return TRUE; }
int *davar_readmultiple_test_1(TESTNAMELIST *argp, CLIENT *clnt) { /* Code fragment to get client info */ static int result; int i; daVarCallBackList *next,*this; TESTNAMELIST *argcopy; SVCXPRT *transp; struct sockaddr_in *sock,*sockcopy; /* printf("IN davar_readmultiple_test_1\n");*/ sock = (struct sockaddr_in *) svc_getcaller(((struct svc_req *) clnt)->rq_xprt); /* Copy the arguments */ argcopy = (TESTNAMELIST *) malloc(sizeof(TESTNAMELIST)); argcopy->test_condition = (char *) malloc(strlen(argp->test_condition)+1); strcpy(argcopy->test_condition, argp->test_condition); argcopy->max_time_wait = argp->max_time_wait; argcopy->max_event_wait = argp->max_event_wait; argcopy->prog = argp->prog; argcopy->vers = argp->vers; argcopy->NAMELISTP = (NAMELIST *) malloc(sizeof(NAMELIST)); argcopy->NAMELISTP->NAMELIST_len = argp->NAMELISTP->NAMELIST_len; argcopy->NAMELISTP->NAMELIST_val = (char **) malloc(argp->NAMELISTP->NAMELIST_len*sizeof(char *)); for(i=0; i<argp->NAMELISTP->NAMELIST_len; i++) { argcopy->NAMELISTP->NAMELIST_val[i] = (char *) malloc(strlen(argp->NAMELISTP->NAMELIST_val[i])+1); strcpy(argcopy->NAMELISTP->NAMELIST_val[i] ,argp->NAMELISTP->NAMELIST_val[i]); } /* Copy the socket */ sockcopy = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in)); bzero(sockcopy,sizeof(struct sockaddr_in)); bcopy(sock,sockcopy,sizeof(struct sockaddr_in)); /* printf("Socket copied\n");*/ next = thCallBackListP; this = thCallBackListP = (daVarCallBackList *) malloc(sizeof(daVarCallBackList)); this->sock_in = sockcopy; /* Actually need to copy structure */ this->list = argcopy; this->start_time = time(0); /* Record when request came in */ this->next = next; #if 0 hp = (struct hostent *) gethostbyaddr((char *)&sockcopy->sin_addr, sizeof(sockcopy->sin_addr),AF_INET); printf("%s %s\n", inet_ntoa(sockcopy->sin_addr), hp->h_name); #endif result = S_SUCCESS; return(&result); }
//Servicio de QUIT. bool_t quit_rpc_1_svc(char* byte, char *result, struct svc_req *rqstp) { //Petición de salida. struct sockaddr_in *client_addr = svc_getcaller(rqstp->rq_xprt); printf("s> %s:%d quit\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); *result = CODE_QUIT; return TRUE; }
//Servicio de CHECK. bool_t check_rpc_1_svc(struct check_pet *data_in, struct check_res *data_out, struct svc_req *rqstp) { //Petición check. struct sockaddr_in *client_addr = svc_getcaller(rqstp->rq_xprt); if(ntohl(data_in->iter) == 0) { //Contador de estadísticas. pthread_mutex_lock(&stats_mutex[3]); stats[3]++; pthread_mutex_unlock(&stats_mutex[3]); printf("s> %s:%d init check %u %u\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), ntohl(data_in->total_length), ntohl(data_in->hash_client)); } //Copiamos información de la petición a la respuesta. data_out->iter = data_in->iter; data_out->total_iter = data_in->total_iter; data_out->total_length = data_in->total_length; data_out->hash_client = data_in->hash_client; //Hash chars. unsigned int i, hash_local = 0; for(i = 0; i < ntohl(data_in->text_length); i++) { hash_local = hash_local + data_in->text[i] % HASH_MOD; } //Actualizamos el hash. data_out->hash_local = htonl(hash_local); data_out->hash = htonl((hash_local + ntohl(data_in->hash)) % HASH_MOD); //(DEBUG) Información sobre la iteración del check. if(DEBUG) { printf("s> %s:%d check iter[%d] %u (%u)\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), ntohl(data_in->iter), hash_local, ntohl(data_in->text_length)); } //Resultado de check. if(ntohl(data_out->iter) == ntohl(data_out->total_iter) - 1) { if(data_out->hash == data_out->hash_client) { data_out->check = CHECK_OK; } else { data_out->check = CHECK_FAIL; } char *check_string; if(data_out->check == CHECK_OK) { check_string = CHECK_STRING_OK; } else if(data_out->check == CHECK_FAIL) { check_string = CHECK_STRING_FAIL; } printf("s> %s:%d check = %s\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), check_string); } return TRUE; }
int yp_check(struct svc_req *req) { struct sockaddr_in *caller; caller = svc_getcaller(req->rq_xprt); /* * We might want to know who we allow here. */ return (0); }
/* * Handles incoming LDM-4 RPC NULLPROC requests (only). This method is * directly and repeatedly invoked by the RPC layer after svc_run(3NSL) is * invoked. * * rqstp The RPC request. * transp The server-side RPC transport. */ void ldmprog_4(struct svc_req *rqstp, register SVCXPRT *transp) { if (rqstp->rq_proc == 0) { /* NULLPROC */ unotice("ldmprog_4: ldmping from %s", hostbyaddr((struct sockaddr_in*)svc_getcaller(transp))); (void)svc_sendreply(transp, (xdrproc_t) xdr_void, (char *)NULL); } else { svcerr_noproc(transp); } }
char *svc_getcaller_test(union u_argument *inVar, SVCXPRT *transp) { //In this function we test svc_getcaller function basically (simple call) struct sockaddr_in *sa = NULL; static int result; sa = svc_getcaller (transp); //If the result is not NULL we consider that function call succeeds //so returns 0 (PASS) result = (sa != NULL) ? 0 : 1; return (char *)&result; }
void * nlm4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp) { static nlm4_res result; if (debug_level) log_from_addr("nlm4_granted_msg", rqstp); result.cookie = arg->cookie; result.stat.stat = nlm4_granted; transmit4_result(NLM4_GRANTED_RES, &result, svc_getcaller(rqstp->rq_xprt)); return NULL; }
//Servicio de SWAP. bool_t swap_rpc_1_svc(struct swap_data* data_in, struct swap_data *data_out, struct svc_req *rqstp) { //Petición de intercambio de letras. struct sockaddr_in *client_addr = svc_getcaller(rqstp->rq_xprt); if(ntohl(data_in->iter) == 0) { //Contador de estadísticas. pthread_mutex_lock(&stats_mutex[1]); stats[1]++; pthread_mutex_unlock(&stats_mutex[1]); printf("s> %s:%d init swap %u\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), ntohl(data_in->total_length)); } //Copiamos información de la petición a la respuesta. data_out->iter = data_in->iter; data_out->total_iter = data_in->total_iter; data_out->total_length = data_in->total_length; data_out->text_length = data_in->text_length; //Swap chars. unsigned int i, swapped_local = 0; for(i = 0; i < ntohl(data_in->text_length); i++) { if(data_in->text[i] != tolower(data_in->text[i])) { data_out->text[i] = tolower(data_in->text[i]); swapped_local++; } else if(data_in->text[i] != toupper(data_in->text[i])) { data_out->text[i] = toupper(data_in->text[i]); swapped_local++; } else { data_out->text[i] = data_in->text[i]; } } //Actualizamos el número de swaps. data_out->swapped_local = htonl(swapped_local); data_out->swapped = htonl(swapped_local + ntohl(data_in->swapped)); //(DEBUG) Información sobre la iteración del swap. if(DEBUG) { printf("s> %s:%d swap iter[%d] %u/%u\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), ntohl(data_in->iter), swapped_local, ntohl(data_in->text_length)); } //Resultado de swap. if(ntohl(data_out->iter) == ntohl(data_out->total_iter) - 1) { printf("s> %s:%d swap = %u\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), ntohl(data_out->swapped)); } return TRUE; }
void * nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp) { static nlm_res res; if (debug_level) log_from_addr("nlm_granted_msg", rqstp); res.cookie = arg->cookie; res.stat.stat = nlm_granted; transmit_result(NLM_GRANTED_RES, &res, (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); return (NULL); }
void * nlm4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp) { static nlm4_res result; if (debug_level) log_from_addr("nlm4_unlock_msg", rqstp); result.stat.stat = unlock(&arg->alock, LOCK_V4); result.cookie = arg->cookie; transmit4_result(NLM4_UNLOCK_RES, &result, svc_getcaller(rqstp->rq_xprt)); return NULL; }
void * nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp) { nlm_testres result; static char dummy; struct sockaddr_in *addr; CLIENT *cli; int success; struct timeval timeo; struct nlm4_lock arg4; struct nlm4_holder *holder; nlmtonlm4(&arg->alock, &arg4); if (debug_level) log_from_addr("nlm_test_msg", rqstp); holder = testlock(&arg4, 0); result.cookie = arg->cookie; if (holder == NULL) { result.stat.stat = nlm_granted; } else { result.stat.stat = nlm_denied; memcpy(&result.stat.nlm_testrply_u.holder, holder, sizeof(struct nlm_holder)); result.stat.nlm_testrply_u.holder.l_offset = (unsigned int)holder->l_offset; result.stat.nlm_testrply_u.holder.l_len = (unsigned int)holder->l_len; } /* * nlm_test has different result type to the other operations, so * can't use transmit_result() in this case */ addr = svc_getcaller(rqstp->rq_xprt); if ((cli = get_client(addr, NLM_VERS)) != NULL) { /* No timeout - not expecting response */ timerclear(&timeo); success = clnt_call(cli, NLM_TEST_RES, xdr_nlm_testres, &result, xdr_void, &dummy, timeo); if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d", success); } return NULL; }
/* * Purpose: Log name of function called and source address * Returns: Nothing * Notes: Extracts the source address from the transport handle * passed in as part of the called procedure specification */ static void log_from_addr(char *fun_name, struct svc_req *req) { struct sockaddr_in *addr; struct hostent *host; char hostname_buf[HOST_NAME_MAX+1]; addr = svc_getcaller(req->rq_xprt); host = gethostbyaddr((char *) &(addr->sin_addr), addr->sin_len, AF_INET); if (host) strlcpy(hostname_buf, host->h_name, sizeof(hostname_buf)); else strlcpy(hostname_buf, inet_ntoa(addr->sin_addr), sizeof hostname_buf); syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf); }
void * nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp) { static nlm_res result; struct nlm4_lock arg4; nlmtonlm4(&arg->alock, &arg4); if (debug_level) log_from_addr("nlm_unlock_msg", rqstp); result.stat.stat = unlock(&arg4, 0); result.cookie = arg->cookie; transmit_result(NLM_UNLOCK_RES, &result, svc_getcaller(rqstp->rq_xprt)); return NULL; }
void * nlm4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp) { static nlm4_res result; if (debug_level) log_from_addr("nlm4_cancel_msg", rqstp); result.cookie = arg->cookie; /* * Since at present we never return 'nlm_blocked', there can never be * a lock to cancel, so this call always fails. */ result.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4); transmit4_result(NLM4_CANCEL_RES, &result, svc_getcaller(rqstp->rq_xprt)); return NULL; }
int check_setunset(SVCXPRT *xprt, SVCXPRT *ludp_xprt, SVCXPRT *ltcp_xprt, u_long proc, u_long prog, u_long port) { struct sockaddr_in *addr = svc_getcaller(xprt); if (xprt != ludp_xprt && xprt != ltcp_xprt) { #ifdef HOSTS_ACCESS (void) good_client(addr); /* because of side effects */ #endif log_bad_owner(addr, proc, prog); return (FALSE); } if (port && !check_privileged_port(addr, proc, prog, port)) return (FALSE); if (verboselog) log_client(addr, proc, prog); return (TRUE); }
/* * For an RPC request, look up the NFS client info along with the * list of directories exported to that client. */ nfs_client * auth_clnt(struct svc_req *rqstp) { nfs_client *cp = NULL; struct in_addr addr = svc_getcaller(rqstp->rq_xprt)->sin_addr; /* Get the client and list of exports */ if ((cp = auth_clientbyaddr(addr)) != NULL) return cp; /* We don't know you */ if (trace_spoof) { dbg_printf(__FILE__, __LINE__, L_ERROR, "Unauthorized access by NFS client %s.\n", inet_ntoa(addr)); } return (NULL); }
//Servicio de PING. bool_t ping_rpc_1_svc(char* byte, char *result, struct svc_req *rqstp) { //Contador de estadísticas. pthread_mutex_lock(&stats_mutex[0]); stats[0]++; pthread_mutex_unlock(&stats_mutex[0]); //Petición de ping. struct sockaddr_in *client_addr = svc_getcaller(rqstp->rq_xprt); printf("s> %s:%d ping\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); if(*byte == CODE_PING) { *result = CODE_PING; return TRUE; } else { *result = CODE_ERROR; return FALSE; } }
nfs_mount * auth_path(nfs_client * cp, struct svc_req * rqstp, char *path) { nfs_mount *mp; /* Check if the specified client is permitted to access this */ if ((mp = auth_match_mount(cp, path)) == NULL) { if (cp->flags != 0 || trace_spoof) { dbg_printf(__FILE__, __LINE__, L_ERROR, "NFS client %s tried to access %s\n", cp->clnt_name, path); } return NULL; } /* Check request originated on a privileged port. */ if (!allow_non_root && mp->o.secure_port && !SECURE_PORT(svc_getcaller(rqstp->rq_xprt)->sin_port)) { dbg_printf(__FILE__, __LINE__, L_ERROR, "NFS request from %s originated on insecure port, %s\n", cp->clnt_name, "psychoanalysis suggested"); return (NULL); } if (log_level_enabled(D_AUTH)) { dbg_printf(__FILE__, __LINE__, D_AUTH, "auth_path(%s): mount point %s, (%s%s%s%s%s)\n", path, mp->path, mp->o.all_squash ? "all_squash " : (mp->o. root_squash ? "root_squash " : ""), (mp->o.uidmap == map_daemon) ? "uidmap " : "", mp->o.secure_port ? "secure " : "insecure ", mp->o.link_relative ? "linkrel " : "", mp->o.read_only ? "ro" : "rw"); } return mp; }
void * nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp) { static nlm_res result; struct nlm4_lockargs arg4; nlmtonlm4(&arg->alock, &arg4.alock); arg4.cookie = arg->cookie; arg4.block = arg->block; arg4.exclusive = arg->exclusive; arg4.reclaim = arg->reclaim; arg4.state = arg->state; if (debug_level) log_from_addr("nlm_lock_msg", rqstp); result.cookie = arg->cookie; result.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON); transmit_result(NLM_LOCK_RES, &result, svc_getcaller(rqstp->rq_xprt)); return NULL; }
//Servicio de HASH. bool_t hash_rpc_1_svc(struct hash_pet *data_in, struct hash_res *data_out, struct svc_req *rqstp) { //Petición de hash. struct sockaddr_in *client_addr = svc_getcaller(rqstp->rq_xprt); if(ntohl(data_in->iter) == 0) { //Contador de estadísticas. pthread_mutex_lock(&stats_mutex[2]); stats[2]++; pthread_mutex_unlock(&stats_mutex[2]); printf("s> %s:%d init hash %u\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), ntohl(data_in->total_length)); } //Copiamos información de la petición a la respuesta. data_out->iter = data_in->iter; data_out->total_iter = data_in->total_iter; data_out->total_length = data_in->total_length; //Hash chars. unsigned int i, hash_local = 0; for(i = 0; i < ntohl(data_in->text_length); i++) { hash_local = hash_local + data_in->text[i] % HASH_MOD; } //Actualizamos el hash. data_out->hash_local = htonl(hash_local); data_out->hash = htonl((hash_local + ntohl(data_in->hash)) % HASH_MOD); //(DEBUG) Información sobre la iteración del hash. if(DEBUG) { printf("s> %s:%d hash iter[%d] %u (%u)\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), ntohl(data_in->iter), hash_local, ntohl(data_in->text_length)); } //Resultado de hash. if(ntohl(data_out->iter) == ntohl(data_out->total_iter) - 1) { printf("s> %s:%d hash = %u\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), ntohl(data_out->hash)); } return TRUE; }
float * lirecan_1_svc(int *argp, struct svc_req *rqstp) { static float result; struct sockaddr_in *adr; int ipad; /* * insert server code here */ printf("accès à la voie n° %d\n",*argp); adr=svc_getcaller(rqstp->rq_xprt); ipad=ntohl(adr->sin_addr.s_addr); printf("par %d.%d.%d.%d\n", (ipad >> 24) & 0xFF, (ipad >> 16) & 0xFF, (ipad >> 8) & 0xFF, (ipad ) & 0xFF); result=3.1415927; return &result; }
int resolv_req(bool *fwding, CLIENT **client, int *pid, char *tp, SVCXPRT *xprt, struct ypreq_key *req, char *map) { enum clnt_stat stat; struct timeval tv; struct ypfwdreq_key4 fwd_req4; struct ypfwdreq_key6 fwd_req6; struct in6_addr in6; int byname, byaddr; int byname_v6, byaddr_v6; #ifdef TDRPC struct sockaddr_in *addrp; #else struct netbuf *nb; char *uaddr; char *cp; int i; sa_family_t caller_af = AF_UNSPEC; struct sockaddr_in *sin4; struct sockaddr_in6 *sin6; #endif if (! *fwding) return (FALSE); byname = strcmp(map, "hosts.byname") == 0; byaddr = strcmp(map, "hosts.byaddr") == 0; byname_v6 = strcmp(map, "ipnodes.byname") == 0; byaddr_v6 = strcmp(map, "ipnodes.byaddr") == 0; if ((!byname && !byaddr && !byname_v6 && !byaddr_v6) || req->keydat.dsize == 0 || req->keydat.dptr[0] == '\0' || !isascii(req->keydat.dptr[0]) || !isgraph(req->keydat.dptr[0])) { /* default status is YP_NOKEY */ return (FALSE); } #ifdef TDRPC fwd_req4.map = map; fwd_req4.keydat = req->keydat; fwd_req4.xid = svc_getxid(xprt); addrp = svc_getcaller(xprt); fwd_req4.ip = addrp->sin_addr.s_addr; fwd_req4.port = addrp->sin_port; #else /* * In order to tell if we have an IPv4 or IPv6 caller address, * we must know that nb->buf is a (sockaddr_in *) or a * (sockaddr_in6 *). Hence, we might as well dispense with the * conversion to uaddr and parsing of same that this section * of the code previously involved itself in. */ nb = svc_getrpccaller(xprt); if (nb != 0) caller_af = ((struct sockaddr_storage *)nb->buf)->ss_family; if (caller_af == AF_INET6) { fwd_req6.map = map; fwd_req6.keydat = req->keydat; fwd_req6.xid = svc_getxid(xprt); sin6 = (struct sockaddr_in6 *)nb->buf; fwd_req6.addr = (uint32_t *)&in6; memcpy(fwd_req6.addr, sin6->sin6_addr.s6_addr, sizeof (in6)); fwd_req6.port = ntohs(sin6->sin6_port); } else if (caller_af == AF_INET) { fwd_req4.map = map; fwd_req4.keydat = req->keydat; fwd_req4.xid = svc_getxid(xprt); sin4 = (struct sockaddr_in *)nb->buf; fwd_req4.ip = ntohl(sin4->sin_addr.s_addr); fwd_req4.port = ntohs(sin4->sin_port); } else { syslog(LOG_ERR, "unknown caller IP address family %d", caller_af); return (FALSE); } #endif /* Restart resolver if it died. (possible overkill) */ if (kill(*pid, 0)) { syslog(LOG_INFO, "Restarting resolv server: old one (pid %d) died.\n", *pid); if (*client != NULL) clnt_destroy (*client); setup_resolv(fwding, pid, client, tp, 0 /* transient p# */); if (!*fwding) { syslog(LOG_ERR, "can't restart resolver: ending resolv service.\n"); return (FALSE); } } /* may need to up timeout */ tv.tv_sec = 10; tv.tv_usec = 0; if (caller_af == AF_INET6) { stat = clnt_call(*client, YPDNSPROC6, xdr_ypfwdreq_key6, (char *)&fwd_req6, xdr_void, 0, tv); } else { stat = clnt_call(*client, YPDNSPROC4, xdr_ypfwdreq_key4, (char *)&fwd_req4, xdr_void, 0, tv); } if (stat == RPC_SUCCESS) /* expected */ return (TRUE); else { /* Over kill error recovery */ /* make one attempt to restart service before turning off */ syslog(LOG_INFO, "Restarting resolv server: old one not responding.\n"); if (!kill(*pid, 0)) kill (*pid, SIGINT); /* cleanup old one */ if (*client != NULL) clnt_destroy (*client); setup_resolv(fwding, pid, client, tp, 0 /* transient p# */); if (!*fwding) { syslog(LOG_ERR, "can't restart resolver: ending resolv service.\n"); return (FALSE); } if (caller_af == AF_INET6) { stat = clnt_call(*client, YPDNSPROC6, xdr_ypfwdreq_key6, (char *)&fwd_req6, xdr_void, 0, tv); } else { stat = clnt_call(*client, YPDNSPROC4, xdr_ypfwdreq_key4, (char *)&fwd_req4, xdr_void, 0, tv); } if (stat == RPC_SUCCESS) /* expected */ return (TRUE); else { /* no more restarts */ clnt_destroy (*client); *fwding = FALSE; /* turn off fwd'ing */ syslog(LOG_ERR, "restarted resolver not responding: ending resolv service.\n"); return (FALSE); } } }
static bool_t pmapproc_change(struct svc_req *rqstp, SVCXPRT *xprt, unsigned long op) { struct pmap reg; RPCB rpcbreg; long ans; struct sockcred *sc; char uidbuf[32]; if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) { svcerr_decode(xprt); return (FALSE); } #ifdef RPCBIND_DEBUG if (debugging) fprintf(stderr, "%s request for (%lu, %lu) : ", op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET", reg.pm_prog, reg.pm_vers); #endif if (!check_access(xprt, op, ®, PMAPVERS)) { svcerr_weakauth(xprt); return FALSE; } (void)svc_getcaller(xprt); sc = __svc_getcallercreds(xprt); /* * Can't use getpwnam here. We might end up calling ourselves * and looping. */ if (sc == NULL) rpcbreg.r_owner = __UNCONST(rpcbind_unknown); else if (sc->sc_uid == 0) rpcbreg.r_owner = __UNCONST(rpcbind_superuser); else { /* r_owner will be strdup-ed later */ snprintf(uidbuf, sizeof uidbuf, "%d", sc->sc_uid); rpcbreg.r_owner = uidbuf; } rpcbreg.r_prog = reg.pm_prog; rpcbreg.r_vers = reg.pm_vers; if (op == PMAPPROC_SET) { char buf[32]; snprintf(buf, sizeof(buf), "0.0.0.0.%d.%d", (int)((reg.pm_port >> 8) & 0xff), (int)(reg.pm_port & 0xff)); rpcbreg.r_addr = buf; if (reg.pm_prot == IPPROTO_UDP) { rpcbreg.r_netid = __UNCONST(udptrans); } else if (reg.pm_prot == IPPROTO_TCP) { rpcbreg.r_netid = __UNCONST(tcptrans); } else { ans = FALSE; goto done_change; } ans = map_set(&rpcbreg, rpcbreg.r_owner); } else if (op == PMAPPROC_UNSET) {
/** * Returns an identifier of the remote client. * * @param[in] rqstp Client-request object. */ const char* rpc_getClientId( struct svc_req* const rqstp) { return hostbyaddr(svc_getcaller(rqstp->rq_xprt)); }
enum auth_stat gssrpc__svcauth_gssapi( register struct svc_req *rqst, register struct rpc_msg *msg, bool_t *no_dispatch) { XDR xdrs; auth_gssapi_creds creds; auth_gssapi_init_arg call_arg; auth_gssapi_init_res call_res; gss_buffer_desc output_token, in_buf, out_buf; gss_cred_id_t server_creds; struct gss_channel_bindings_struct bindings, *bindp; OM_uint32 gssstat, minor_stat, time_rec; struct opaque_auth *cred, *verf; svc_auth_gssapi_data *client_data; int i; enum auth_stat ret; OM_uint32 ret_flags; uint32_t seq_num; PRINTF(("svcauth_gssapi: starting\n")); /* clean up expired entries */ clean_client(); /* use AUTH_NONE until there is a client_handle */ rqst->rq_xprt->xp_auth = &svc_auth_none; memset((char *) &call_res, 0, sizeof(call_res)); creds.client_handle.length = 0; creds.client_handle.value = NULL; cred = &msg->rm_call.cb_cred; verf = &msg->rm_call.cb_verf; if (cred->oa_length == 0) { PRINTF(("svcauth_gssapi: empty creds, failing\n")); LOG_MISCERR("empty client credentials"); ret = AUTH_BADCRED; goto error; } PRINTF(("svcauth_gssapi: decoding credentials\n")); xdrmem_create(&xdrs, cred->oa_base, cred->oa_length, XDR_DECODE); memset((char *) &creds, 0, sizeof(creds)); if (! xdr_authgssapi_creds(&xdrs, &creds)) { PRINTF(("svcauth_gssapi: failed decoding creds\n")); LOG_MISCERR("protocol error in client credentials"); xdr_free(xdr_authgssapi_creds, &creds); XDR_DESTROY(&xdrs); ret = AUTH_BADCRED; goto error; } XDR_DESTROY(&xdrs); PRINTF(("svcauth_gssapi: got credentials, version %d, client_handle len %d\n", creds.version, (int) creds.client_handle.length)); if (creds.version != 2) { PRINTF(("svcauth_gssapi: bad credential version\n")); LOG_MISCERR("unsupported client credentials version"); ret = AUTH_BADCRED; goto error; } #ifdef DEBUG_GSSAPI if (svc_debug_gssapi) { if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_EXIT) { PRINTF(("svcauth_gssapi: GSSAPI_EXIT, cleaning up\n")); svc_sendreply(rqst->rq_xprt, xdr_void, NULL); xdr_free(xdr_authgssapi_creds, &creds); cleanup(); exit(0); } } #endif /* * If this is an auth_msg and proc is GSSAPI_INIT, then create a * client handle for this client. Otherwise, look up the * existing handle. */ if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_INIT) { if (creds.client_handle.length != 0) { PRINTF(("svcauth_gssapi: non-empty handle on GSSAPI_INIT\n")); LOG_MISCERR("protocol error in client handle"); ret = AUTH_FAILED; goto error; } PRINTF(("svcauth_gssapi: GSSAPI_INIT, creating client.\n")); client_data = create_client(); if (client_data == NULL) { PRINTF(("svcauth_gssapi: create_client failed\n")); LOG_MISCERR("internal error creating client record"); ret = AUTH_FAILED; goto error; } } else { if (creds.client_handle.length == 0) { PRINTF(("svcauth_gssapi: expected non-empty creds\n")); LOG_MISCERR("protocol error in client credentials"); ret = AUTH_FAILED; goto error; } PRINTF(("svcauth_gssapi: incoming client_handle %d, len %d\n", *((uint32_t *) creds.client_handle.value), (int) creds.client_handle.length)); client_data = get_client(&creds.client_handle); if (client_data == NULL) { PRINTF(("svcauth_gssapi: client_handle lookup failed\n")); LOG_MISCERR("invalid client handle received"); ret = AUTH_BADCRED; goto error; } PRINTF(("svcauth_gssapi: client_handle lookup succeeded\n")); } /* any response we send will use client_handle, so set it now */ call_res.client_handle.length = sizeof(client_data->key); call_res.client_handle.value = (char *) &client_data->key; /* mark this call as using AUTH_GSSAPI via client_data's SVCAUTH */ rqst->rq_xprt->xp_auth = &client_data->svcauth; if (client_data->established == FALSE) { PRINTF(("svcauth_gssapi: context is not established\n")); if (creds.auth_msg == FALSE) { PRINTF(("svcauth_gssapi: expected auth_msg TRUE\n")); LOG_MISCERR("protocol error on incomplete connection"); ret = AUTH_REJECTEDCRED; goto error; } /* * If the context is not established, then only GSSAPI_INIT * and _CONTINUE requests are valid. */ if (rqst->rq_proc != AUTH_GSSAPI_INIT && rqst->rq_proc != AUTH_GSSAPI_CONTINUE_INIT) { PRINTF(("svcauth_gssapi: unacceptable procedure %d\n", rqst->rq_proc)); LOG_MISCERR("protocol error on incomplete connection"); ret = AUTH_FAILED; goto error; } /* call is for us, deserialize arguments */ memset(&call_arg, 0, sizeof(call_arg)); if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg, &call_arg)) { PRINTF(("svcauth_gssapi: cannot decode args\n")); LOG_MISCERR("protocol error in procedure arguments"); ret = AUTH_BADCRED; goto error; } /* * Process the call arg version number. * * Set the krb5_gss backwards-compatibility mode based on client * version. This controls whether the AP_REP message is * encrypted with the session key (version 2+, correct) or the * session subkey (version 1, incorrect). This function can * never fail, so we don't bother checking its return value. */ switch (call_arg.version) { case 1: case 2: LOG_MISCERR("Warning: Accepted old RPC protocol request"); call_res.version = 1; break; case 3: case 4: /* 3 and 4 are essentially the same, don't bother warning */ call_res.version = call_arg.version; break; default: PRINTF(("svcauth_gssapi: bad GSSAPI_INIT version\n")); LOG_MISCERR("unsupported GSSAPI_INIT version"); ret = AUTH_BADCRED; goto error; } #ifdef GSS_BACKWARD_HACK krb5_gss_set_backward_mode(&minor_stat, call_arg.version == 1); #endif if (call_arg.version >= 3) { memset(&bindings, 0, sizeof(bindings)); bindings.application_data.length = 0; bindings.initiator_addrtype = GSS_C_AF_INET; bindings.initiator_address.length = 4; bindings.initiator_address.value = &svc_getcaller(rqst->rq_xprt)->sin_addr.s_addr; if (rqst->rq_xprt->xp_laddrlen > 0) { bindings.acceptor_addrtype = GSS_C_AF_INET; bindings.acceptor_address.length = 4; bindings.acceptor_address.value = &rqst->rq_xprt->xp_laddr.sin_addr.s_addr; } else { LOG_MISCERR("cannot get local address"); ret = AUTH_FAILED; goto error; } bindp = &bindings; } else { bindp = GSS_C_NO_CHANNEL_BINDINGS; } /* * If the client's server_creds is already set, use it. * Otherwise, try each credential in server_creds_list until * one of them succeedes, then set the client server_creds * to that. If all fail, the client's server_creds isn't * set (which is fine, because the client will be gc'ed * anyway). * * If accept_sec_context returns something other than * success and GSS_S_FAILURE, then assume different * credentials won't help and stop looping. * * Note that there are really two cases here: (1) the client * has a server_creds already, and (2) it does not. They * are both written in the same loop so that there is only * one textual call to gss_accept_sec_context; in fact, in * case (1), the loop is executed exactly once. */ for (i = 0; i < server_creds_count; i++) { if (client_data->server_creds != NULL) { PRINTF(("svcauth_gssapi: using's clients server_creds\n")); server_creds = client_data->server_creds; } else { PRINTF(("svcauth_gssapi: trying creds %d\n", i)); server_creds = server_creds_list[i]; } /* Free previous output_token from loop */ if(i != 0) gss_release_buffer(&minor_stat, &output_token); call_res.gss_major = gss_accept_sec_context(&call_res.gss_minor, &client_data->context, server_creds, &call_arg.token, bindp, &client_data->client_name, NULL, &output_token, &ret_flags, &time_rec, NULL); if (server_creds == client_data->server_creds) break; PRINTF(("accept_sec_context returned 0x%x 0x%x wrong-princ=%#x\n", call_res.gss_major, call_res.gss_minor, (int) KRB5KRB_AP_WRONG_PRINC)); if (call_res.gss_major == GSS_S_COMPLETE || call_res.gss_major == GSS_S_CONTINUE_NEEDED) { /* server_creds was right, set it! */ PRINTF(("svcauth_gssapi: creds are correct, storing\n")); client_data->server_creds = server_creds; client_data->server_name = server_name_list[i]; break; } else if (call_res.gss_major != GSS_S_FAILURE #ifdef GSSAPI_KRB5 /* * hard-coded because there is no other way * to prevent all GSS_S_FAILURES from * returning a "wrong principal in request" * error */ || ((krb5_error_code) call_res.gss_minor != (krb5_error_code) KRB5KRB_AP_WRONG_PRINC) #endif ) { break; } } gssstat = call_res.gss_major; minor_stat = call_res.gss_minor; /* done with call args */ xdr_free(xdr_authgssapi_init_arg, &call_arg); PRINTF(("svcauth_gssapi: accept_sec_context returned %#x %#x\n", call_res.gss_major, call_res.gss_minor)); if (call_res.gss_major != GSS_S_COMPLETE && call_res.gss_major != GSS_S_CONTINUE_NEEDED) { AUTH_GSSAPI_DISPLAY_STATUS(("accepting context", call_res.gss_major, call_res.gss_minor)); if (log_badauth != NULL) (*log_badauth)(call_res.gss_major, call_res.gss_minor, &rqst->rq_xprt->xp_raddr, log_badauth_data); gss_release_buffer(&minor_stat, &output_token); svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res, (caddr_t) &call_res); *no_dispatch = TRUE; ret = AUTH_OK; goto error; } if (output_token.length != 0) { PRINTF(("svcauth_gssapi: got new output token\n")); GSS_COPY_BUFFER(call_res.token, output_token); } if (gssstat == GSS_S_COMPLETE) { client_data->seq_num = rand(); client_expire(client_data, (time_rec == GSS_C_INDEFINITE ? INDEF_EXPIRE : time_rec) + time(0)); PRINTF(("svcauth_gssapi: context established, isn %d\n", client_data->seq_num)); if (auth_gssapi_seal_seq(client_data->context, client_data->seq_num, &call_res.signed_isn) == FALSE) { ret = AUTH_FAILED; LOG_MISCERR("internal error sealing sequence number"); gss_release_buffer(&minor_stat, &output_token); goto error; } } PRINTF(("svcauth_gssapi: sending reply\n")); svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res, (caddr_t) &call_res); *no_dispatch = TRUE; /* * If appropriate, set established to TRUE *after* sending * response (otherwise, the client will receive the final * token encrypted) */ if (gssstat == GSS_S_COMPLETE) { gss_release_buffer(&minor_stat, &call_res.signed_isn); client_data->established = TRUE; } gss_release_buffer(&minor_stat, &output_token); } else { PRINTF(("svcauth_gssapi: context is established\n")); /* check the verifier */ PRINTF(("svcauth_gssapi: checking verifier, len %d\n", verf->oa_length)); in_buf.length = verf->oa_length; in_buf.value = verf->oa_base; if (auth_gssapi_unseal_seq(client_data->context, &in_buf, &seq_num) == FALSE) { ret = AUTH_BADVERF; LOG_MISCERR("internal error unsealing sequence number"); goto error; } if (seq_num != client_data->seq_num + 1) { PRINTF(("svcauth_gssapi: expected isn %d, got %d\n", client_data->seq_num + 1, seq_num)); if (log_badverf != NULL) (*log_badverf)(client_data->client_name, client_data->server_name, rqst, msg, log_badverf_data); ret = AUTH_REJECTEDVERF; goto error; } client_data->seq_num++; PRINTF(("svcauth_gssapi: seq_num %d okay\n", seq_num)); /* free previous response verifier, if any */ if (client_data->prev_verf.length != 0) { gss_release_buffer(&minor_stat, &client_data->prev_verf); client_data->prev_verf.length = 0; } /* prepare response verifier */ seq_num = client_data->seq_num + 1; if (auth_gssapi_seal_seq(client_data->context, seq_num, &out_buf) == FALSE) { ret = AUTH_FAILED; LOG_MISCERR("internal error sealing sequence number"); goto error; } client_data->seq_num++; PRINTF(("svcauth_gssapi; response seq_num %d\n", seq_num)); rqst->rq_xprt->xp_verf.oa_flavor = AUTH_GSSAPI; rqst->rq_xprt->xp_verf.oa_base = out_buf.value; rqst->rq_xprt->xp_verf.oa_length = out_buf.length; /* save verifier so it can be freed next time */ client_data->prev_verf.value = out_buf.value; client_data->prev_verf.length = out_buf.length; /* * Message is authentic. If auth_msg if true, process the * call; otherwise, return AUTH_OK so it will be dispatched * to the application server. */ if (creds.auth_msg == TRUE) { /* * If process_token fails, then the token probably came * from an attacker. No response (error or otherwise) * should be returned to the client, since it won't be * accepting one. */ switch (rqst->rq_proc) { case AUTH_GSSAPI_MSG: PRINTF(("svcauth_gssapi: GSSAPI_MSG, getting args\n")); memset(&call_arg, 0, sizeof(call_arg)); if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg, &call_arg)) { PRINTF(("svcauth_gssapi: cannot decode args\n")); LOG_MISCERR("protocol error in call arguments"); xdr_free(xdr_authgssapi_init_arg, &call_arg); ret = AUTH_BADCRED; goto error; } PRINTF(("svcauth_gssapi: processing token\n")); gssstat = gss_process_context_token(&minor_stat, client_data->context, &call_arg.token); /* done with call args */ xdr_free(xdr_authgssapi_init_arg, &call_arg); if (gssstat != GSS_S_COMPLETE) { AUTH_GSSAPI_DISPLAY_STATUS(("processing token", gssstat, minor_stat)); ret = AUTH_FAILED; goto error; } svc_sendreply(rqst->rq_xprt, xdr_void, NULL); *no_dispatch = TRUE; break; case AUTH_GSSAPI_DESTROY: PRINTF(("svcauth_gssapi: GSSAPI_DESTROY\n")); PRINTF(("svcauth_gssapi: sending reply\n")); svc_sendreply(rqst->rq_xprt, xdr_void, NULL); *no_dispatch = TRUE; destroy_client(client_data); rqst->rq_xprt->xp_auth = NULL; break; default: PRINTF(("svcauth_gssapi: unacceptable procedure %d\n", rqst->rq_proc)); LOG_MISCERR("invalid call procedure number"); ret = AUTH_FAILED; goto error; } } else { /* set credentials for app server; comment in svc.c */ /* seems to imply this is incorrect, but I don't see */ /* any problem with it... */ rqst->rq_clntcred = (char *)client_data->client_name; rqst->rq_svccred = (char *)client_data->context; } } if (creds.client_handle.length != 0) { PRINTF(("svcauth_gssapi: freeing client_handle len %d\n", (int) creds.client_handle.length)); xdr_free(xdr_authgssapi_creds, &creds); } PRINTF(("\n")); return AUTH_OK; error: if (creds.client_handle.length != 0) { PRINTF(("svcauth_gssapi: freeing client_handle len %d\n", (int) creds.client_handle.length)); xdr_free(xdr_authgssapi_creds, &creds); } PRINTF(("\n")); return ret; }
hiya_reply_t* hiya_6_svc( prod_class_t *offered, struct svc_req *rqstp) { const char* const pqfname = getQueuePath(); static hiya_reply_t reply; SVCXPRT * const xprt = rqstp->rq_xprt; struct sockaddr_in *upAddr = (struct sockaddr_in*) svc_getcaller(xprt); const char *upName = hostbyaddr(upAddr); int error; int isPrimary; unsigned int maxHereis; static prod_class_t *accept; /* * Open the product-queue for writing. It will be closed by cleanup() * during process termination. */ if (pq) { (void) pq_close(pq); pq = NULL; } error = pq_open(pqfname, PQ_DEFAULT, &pq); if (error) { err_log_and_free(ERR_NEW2(error, NULL, "Couldn't open product-queue \"%s\" for writing: %s", pqfname, PQ_CORRUPT == error ? "The product-queue is inconsistent" : strerror(error)), ERR_FAILURE); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } /* else */ error = down6_init(upName, upAddr, pqfname, pq); if (error) { uerror("Couldn't initialize downstream LDM"); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } else { uinfo("Downstream LDM initialized"); } /* * The previous "accept" is freed here -- rather than freeing the * soon-to-be-allocated "accept" at the end of its block -- because it can * be used in the reply. */ if (accept) { free_prod_class(accept); /* NULL safe */ accept = NULL; } error = lcf_reduceToAcceptable(upName, inet_ntoa(upAddr->sin_addr), offered, &accept, &isPrimary); maxHereis = isPrimary ? UINT_MAX : 0; if (error) { serror("Couldn't validate HIYA"); svcerr_systemerr(xprt); svc_destroy(xprt); exit(error); } else { if (ulogIsDebug()) udebug("intersection: %s", s_prod_class(NULL, 0, accept)); if (accept->psa.psa_len == 0) { uwarn("Empty intersection of HIYA offer from %s (%s) and ACCEPT " "entries", upName, s_prod_class(NULL, 0, offered)); svcerr_weakauth(xprt); svc_destroy(xprt); exit(0); } else { error = down6_set_prod_class(accept); if (error) { if (DOWN6_SYSTEM_ERROR == error) { serror("Couldn't set product class: %s", s_prod_class(NULL, 0, accept)); } else { uerror("Couldn't set product class: %s", s_prod_class(NULL, 0, accept)); } svcerr_systemerr(xprt); svc_destroy(xprt); exit(EXIT_FAILURE); } /* else */ if (clss_eq(offered, accept)) { unotice("hiya6: %s", s_prod_class(NULL, 0, offered)); reply.code = OK; reply.hiya_reply_t_u.max_hereis = maxHereis; } else { if (ulogIsVerbose()) { char off[512]; char acc[512]; (void) s_prod_class(off, sizeof(off), offered), (void) s_prod_class( acc, sizeof(acc), accept); uinfo("hiya6: RECLASS: %s -> %s", off, acc); } reply.code = RECLASS; reply.hiya_reply_t_u.feedPar.prod_class = accept; reply.hiya_reply_t_u.feedPar.max_hereis = maxHereis; } } /* product-intersection != empty set */ } /* successful acl_check_hiya() */ return &reply; }
/** * Feeds or notifies a downstream LDM. This function returns either NULL or a * reply to be sent to the downstream LDM (e.g., a RECLASS message) or * terminates this process (hopefully after sending some data). * * @param xprt [in/out] Pointer to server-side transport handle. * @param want [in] Pointer to subscription by downstream LDM. * May contain a "signature" product-specification. * @param isNotifier [in] Whether or not the upstream LDM is a feeder or a * notifier. * @param maxHereis Maximum HEREIS size parameter. Ignored if "isNotifier" * is true. * @return The reply for the downstream LDM or NULL if no reply * should be made. */ static fornme_reply_t* feed_or_notify( SVCXPRT* const xprt, const prod_class_t* const want, const int isNotifier, const max_hereis_t maxHereis) { struct sockaddr_in downAddr = *svc_getcaller(xprt); ErrorObj* errObj; int status; char* downName = NULL; prod_class_t* origSub = NULL; prod_class_t* allowSub = NULL; const signaturet* signature = NULL; UpFilter* upFilter = NULL; fornme_reply_t* reply = NULL; int isPrimary; static fornme_reply_t theReply; static prod_class_t* uldbSub = NULL; /* * Clean-up from a (possibly) previous invocation */ (void)memset(&theReply, 0, sizeof(theReply)); if (uldbSub != NULL) { free_prod_class(uldbSub); uldbSub = NULL; } downName = strdup(hostbyaddr(&downAddr)); if (NULL == downName) { LOG_ADD1("Couldn't duplicate downstream host name: \"%s\"", hostbyaddr(&downAddr)); log_log(LOG_ERR); svcerr_systemerr(xprt); goto return_or_exit; } set_abbr_ident(downName, isNotifier ? "(noti)" : "(feed)"); /* * Remove any "signature" specification from the subscription. */ if ((errObj = separateProductClass(want, &origSub, &signature)) != NULL) { err_log_and_free(errObj, ERR_FAILURE); svcerr_systemerr(xprt); goto free_down_name; } /* * Get the upstream filter */ errObj = lcf_getUpstreamFilter(downName, &downAddr.sin_addr, origSub, &upFilter); if (errObj) { err_log_and_free(ERR_NEW(0, errObj, "Couldn't get \"upstream\" filter"), ERR_FAILURE); svcerr_systemerr(xprt); goto free_orig_sub; } if (NULL == upFilter) { err_log_and_free(ERR_NEW1(0, NULL, "Upstream filter prevents data-transfer: %s", s_prod_class(NULL, 0, origSub)), ERR_FAILURE); svcerr_weakauth(xprt); goto free_orig_sub; } /* TODO: adjust time? */ /* * Reduce the subscription according to what the downstream host is allowed * to receive. */ status = lcf_reduceToAllowed(downName, &downAddr.sin_addr, origSub, &allowSub); if (status == ENOMEM) { LOG_SERROR0("Couldn't compute wanted/allowed product intersection"); log_log(LOG_ERR); svcerr_systemerr(xprt); goto free_up_filter; } if (status == EINVAL) { LOG_ADD1("Invalid pattern in product-class: %s", s_prod_class(NULL, 0, origSub)); log_log(LOG_WARNING); theReply.code = BADPATTERN; reply = &theReply; goto free_up_filter; } assert(status == 0); (void) logIfReduced(origSub, allowSub, "ALLOW entries"); /* * Reduce the subscription according to existing subscriptions from the * same downstream host and, if `isAntiDosEnabled()` returns `true`, * terminate every previously-existing upstream LDM process that's feeding * (not notifying) a subset of the subscription to the same IP address. * * The following relies on atexit()-registered cleanup for removal of the * entry from the upstream LDM database. */ isPrimary = maxHereis > UINT_MAX / 2; status = uldb_addProcess(getpid(), 6, &downAddr, allowSub, &uldbSub, isNotifier, isPrimary); if (status) { LOG_ADD0("Couldn't add this process to the upstream LDM database"); log_log(LOG_ERR); svcerr_systemerr(xprt); goto free_allow_sub; } (void) logIfReduced(allowSub, uldbSub, "existing subscriptions"); /* * Send a RECLASS reply to the downstream LDM if appropriate. */ if (!clss_eq(origSub, uldbSub)) { theReply.code = RECLASS; if (0 < uldbSub->psa.psa_len) { /* * The downstream LDM is allowed less than it requested and was * entered into the upstream LDM database. */ (void)uldb_remove(getpid()); /* maybe next time */ theReply.fornme_reply_t_u.prod_class = uldbSub; } else { /* * The downstream LDM isn't allowed anything and wasn't entered * into the upstream LDM database. */ static prod_class noSub = { { 0, 0 }, /* TS_ZERO */ { 0, 0 }, /* TS_ZERO */ { 0, (prod_spec *) NULL } }; theReply.fornme_reply_t_u.prod_class = &noSub; } reply = &theReply; goto free_allow_sub; } /* * Reply to the downstream LDM that the subscription will be honored. */ theReply.code = OK; theReply.fornme_reply_t_u.id = (unsigned) getpid(); if (!svc_sendreply(xprt, (xdrproc_t)xdr_fornme_reply_t, (caddr_t)&theReply)) { LOG_ADD0("svc_sendreply(...) failure"); log_log(LOG_ERR); svcerr_systemerr(xprt); goto free_allow_sub; } /* * Wait a second before sending anything to the downstream LDM. */ (void) sleep(1); status = isNotifier ? up6_new_notifier(xprt->xp_sock, downName, &downAddr, uldbSub, signature, getQueuePath(), interval, upFilter) : up6_new_feeder(xprt->xp_sock, downName, &downAddr, uldbSub, signature, getQueuePath(), interval, upFilter, isPrimary); svc_destroy(xprt); /* closes the socket */ exit(status); /* * Reply and error handling: */ free_allow_sub: free_prod_class(allowSub); free_up_filter: upFilter_free(upFilter); free_orig_sub: free_prod_class(origSub); free_down_name: free(downName); return_or_exit: return reply; }
static void mountudp_program_3(struct svc_req *rqstp, register SVCXPRT *transp) { union { dirpath mountudpproc3_mnt_3_arg; } argument; char *result = NULL; xdrproc_t _xdr_argument = NULL, _xdr_result = NULL; char *(*local)(char *, struct svc_req *) = NULL; mountres3 *res = NULL; struct sockaddr_in *sin = NULL; sin = svc_getcaller (transp); inet_ntop (AF_INET, &sin->sin_addr, mnthost, INET_ADDRSTRLEN+1); switch (rqstp->rq_proc) { case NULLPROC: (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); return; case MOUNT3_MNT: _xdr_argument = (xdrproc_t) xdr_dirpath; _xdr_result = (xdrproc_t) xdr_mountres3; local = (char *(*)(char *, struct svc_req *)) mountudpproc3_mnt_3_svc; break; case MOUNT3_UMNT: _xdr_argument = (xdrproc_t) xdr_dirpath; _xdr_result = (xdrproc_t) xdr_mountstat3; local = (char *(*)(char *, struct svc_req *)) mountudpproc3_umnt_3_svc; break; default: svcerr_noproc (transp); return; } memset ((char *)&argument, 0, sizeof (argument)); if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { svcerr_decode (transp); return; } result = (*local)((char *)&argument, rqstp); if (result == NULL) { gf_log (GF_MNT, GF_LOG_DEBUG, "PROC returned error"); svcerr_systemerr (transp); } if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) { gf_log (GF_MNT, GF_LOG_ERROR, "svc_sendreply returned error"); svcerr_systemerr (transp); } if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { gf_log (GF_MNT, GF_LOG_ERROR, "unable to free arguments"); } if (result == NULL) return; /* free the result */ switch (rqstp->rq_proc) { case MOUNT3_MNT: res = (mountres3 *) result; GF_FREE (res->mountres3_u.mountinfo.fhandle.fhandle3_val); GF_FREE (res->mountres3_u.mountinfo.auth_flavors.auth_flavors_val); GF_FREE (res); break; case MOUNT3_UMNT: GF_FREE (result); break; } return; }
/* * find the address of the caller of an RPC procedure. */ struct sockaddr_in * amu_svc_getcaller(SVCXPRT *xprt) { /* glibc 2.2 returns a sockaddr_storage ??? */ return (struct sockaddr_in *) svc_getcaller(xprt); }