int init_listen(int port,int af) { int sock = -1; struct addrinfo hints; struct addrinfo *base_res = NULL; struct addrinfo *res_ptr = NULL; char portstr[32]; int ret; if( port <= 0 ){ return(-1); } sprintf(portstr,"%d",port); memset(&hints,'\0',sizeof(hints)); hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(NULL,portstr,&hints,&base_res); if( ret != 0 ){ fprintf(stderr,"ERROR: getaddrinfo: %s\n",gai_strerror(ret)); return(-1); } for( res_ptr = base_res; res_ptr != NULL; res_ptr = res_ptr->ai_next ){ sock = socket(res_ptr->ai_family,res_ptr->ai_socktype,res_ptr->ai_protocol); if( sock < 0 ){ continue; } set_reuseaddr(sock); set_sndbuf(sock,65535); set_rcvbuf(sock,65535); if( bind(sock,res_ptr->ai_addr,res_ptr->ai_addrlen) < 0 ){ fprintf(stderr,"WARN: bind: %s\n",strerror(errno)); close(sock); sock = -1; continue; } if( listen(sock,BACKLOG_NUMBER) < 0 ){ fprintf(stderr,"WARN: listen: %s\n",strerror(errno)); close(sock); sock = -1; continue; } break; } freeaddrinfo(base_res); base_res = NULL; return(sock); }
int connect2(const char *host,int port,int af) { int sock = -1; struct addrinfo hints; struct addrinfo *base_res = NULL; struct addrinfo *res_ptr = NULL; char portstr[32]; int ret; if( NULL == host || port <= 0 ){ return(-1); } sprintf(portstr,"%d",port); memset(&hints,'\0',sizeof(hints)); hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; ret = getaddrinfo(host,portstr,&hints,&base_res); if( ret != 0 ){ fprintf(stderr,"ERROR: getaddrinfo: %s\n",gai_strerror(ret)); return(-1); } for( res_ptr = base_res; res_ptr != NULL; res_ptr = res_ptr->ai_next ){ sock = socket(res_ptr->ai_family,res_ptr->ai_socktype,res_ptr->ai_protocol); if( sock < 0 ){ continue; } set_sndbuf(sock,65535); set_rcvbuf(sock,65535); if( connect(sock,res_ptr->ai_addr,res_ptr->ai_addrlen) < 0 ){ close(sock); sock = -1; continue; } break; } freeaddrinfo(base_res); base_res = NULL; return(sock); }
int make_socket ( os_socket * sock, unsigned short port, c_bool stream, c_bool reuse, const os_sockaddr_storage * mcip, const char * address ) { int rc = -2; *sock = os_sockNew ((config.useIpv6 ? AF_INET6 : AF_INET), stream ? SOCK_STREAM : SOCK_DGRAM); if (! Q_VALID_SOCKET (*sock)) { print_sockerror ("socket"); return rc; } if (port && reuse && ((rc = set_reuse_options (*sock)) < 0)) { goto fail; } if ( (rc = set_rcvbuf (*sock) < 0) || (rc = set_sndbuf (*sock) < 0) || ((rc = maybe_set_dont_route (*sock)) < 0) || ((rc = bind_socket (*sock, port, address)) < 0) ) { goto fail; } if (! stream) { if ((rc = set_mc_options_transmit (*sock)) < 0) { goto fail; } } if (stream) { #ifdef SO_NOSIGPIPE set_socket_nosigpipe (*sock); #endif #ifdef TCP_NODELAY if (config.tcp_nodelay) { set_socket_nodelay (*sock); } #endif } if (mcip && ((rc = join_mcgroups (*sock, mcip)) < 0)) { goto fail; } return 0; fail: os_sockFree (*sock); *sock = Q_INVALID_SOCKET; return rc; }
static void accept_new(void) { char buffer[MAX_ATM_ADDR_LEN+1]; struct sockaddr_atmsvc addr; struct atm_qos qos; ENTRY *entry; VCC *vcc; int fd,error; socklen_t len,size; len = sizeof(addr); if ((fd = accept(incoming,(struct sockaddr *) &addr,&len)) < 0) { error = errno; diag(COMPONENT,DIAG_ERROR,"accept: %s",strerror(errno)); if (error == EUNATCH) { diag(COMPONENT,DIAG_WARN,"disabling SVCs"); (void) close(incoming); incoming = -1; } return; } /* the following code probably belongs to arp.c ... */ if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) &addr,pretty) < 0) strcpy(buffer,"<atm2text error>"); diag(COMPONENT,DIAG_DEBUG,"Incoming call from %s",buffer); size = sizeof(qos); if (getsockopt(fd,SOL_ATM,SO_ATMQOS,&qos,&size) < 0) diag(COMPONENT,DIAG_FATAL,"getsockopt SO_ATMQOS: %s",strerror(errno)); if (size != sizeof(qos)) diag(COMPONENT,DIAG_FATAL,"SO_ATMQOS: size %d != %d",size,sizeof(qos)); if (ioctl(fd,ATMARP_MKIP,qos.txtp.traffic_class == ATM_NONE ? 0 : CLIP_DEFAULT_IDLETIMER) < 0) { diag(COMPONENT,DIAG_ERROR,"ioctl ATMARP_MKIP: %s",strerror(errno)); (void) do_close(fd); return; } vcc = alloc_t(VCC); vcc->active = 0; vcc->connecting = 0; vcc->fd = fd; if (qos.txtp.traffic_class == ATM_NONE) { vcc->entry = NULL; incoming_unidirectional(vcc); Q_INSERT_HEAD(unidirectional_vccs,vcc); return; } if (merge) { ITF *itf; for (itf = itfs; itf; itf = itf->next) { entry = lookup_addr(itf,&addr); if (entry) { vcc->entry = entry; Q_INSERT_HEAD(entry->vccs,vcc); if (entry->state == as_valid) { if (set_ip(vcc->fd,entry->ip) < 0) { diag(COMPONENT,DIAG_ERROR,"set_ip: %s", strerror(errno)); disconnect_vcc(vcc); } else set_sndbuf(vcc); } return; } } } entry = alloc_entry(1); entry->state = as_invalid; entry->addr = alloc_t(struct sockaddr_atmsvc); *entry->addr = addr; entry->flags = ATF_PUBL; Q_INSERT_HEAD(unknown_incoming,entry); vcc->entry = entry; Q_INSERT_HEAD(entry->vccs,vcc); incoming_call(vcc); }
static int learn(VCC *vcc,uint32_t ip,struct sockaddr_atmsvc *addr) { ENTRY *entry; ITF *itf; VCC *walk,*next; unsigned char *ipp; int result = 0; if (!ip) return 0; ipp = (unsigned char *) &ip; itf = lookup_itf_by_ip(ip); if (!itf) { diag(COMPONENT,DIAG_ERROR,"got unroutable IP address %d.%d.%d.%d", ipp[0],ipp[1],ipp[2],ipp[3]); return 0; } entry = lookup_ip(itf,ip); assert(!vcc || vcc->entry); /* * If the entry on which we received the update isn't dangling but it * doesn't correspond to the one with the address, ... */ if (entry && vcc && vcc->entry->itf && entry != vcc->entry) { diag(COMPONENT,DIAG_DEBUG,"collision on %d.%d.%d.%d",ipp[0],ipp[1], ipp[2],ipp[3]); return 0; } /* * If the entry on which we received the update is dangling and we found * an entry that already describes that IP address, ... */ if (entry && vcc && !vcc->entry->itf) { if (!entry->svc) { diag(COMPONENT,DIAG_ERROR,"attempt to overwrite PVC for IP " "%d.%d.%d.%d",ipp[0],ipp[1],ipp[2],ipp[3]); return 0; } STOP_TIMER(vcc->entry); Q_REMOVE(unknown_incoming,vcc->entry); free(vcc->entry); vcc->entry = entry; Q_INSERT_HEAD(entry->vccs,vcc); set_sndbuf(vcc); entry->flags &= ~ATF_NOVC; assert(!vcc->connecting); if (set_ip(vcc->fd,ip) < 0) { diag(COMPONENT,DIAG_ERROR,"set_ip: %s",strerror(errno)); disconnect_vcc(vcc); vcc = NULL; result = -1; } } /* * If we still don't have an entry, we try to use the entry that already * belongs to the VCC (InARP), or we create a new one (ARP). */ if (!entry) { if (vcc) { entry = vcc->entry; if (!entry->itf) { Q_REMOVE(unknown_incoming,entry); entry->sndbuf = itf->sndbuf; set_sndbuf(vcc); } else if (entry->ip && entry->ip != ip && (entry->flags & ATF_PERM) && !(entry->flags & ATF_ARPSRV)) { diag(COMPONENT,DIAG_ERROR,"ignoring attempt to change IP " "address of permanent entry (to %d.%d.%d.%d)",ipp[0], ipp[1],ipp[2],ipp[3]); return result; } } else { entry = alloc_entry(1); entry->flags = ATF_PUBL; } } if (!atmsvc_addr_in_use(*addr)) addr = NULL; if (entry->addr && addr && (entry->flags & ATF_PERM) && !atm_equal((struct sockaddr *) entry->addr,(struct sockaddr *) addr,0,0)) { diag(COMPONENT,DIAG_ERROR,"ignoring attempt to change ATM address of " "permanent entry"); return result; } if (entry->state == as_valid && entry->ip == ip && (!addr || (entry->addr && atm_equal((struct sockaddr *) entry->addr,(struct sockaddr *) addr,0, 0)))) return result; /* no news */ STOP_TIMER(entry); if (entry->ip != ip) send_notifications(entry,0); entry->ip = ip; if (!entry->itf) { entry->itf = itf; /* @@@ * Need to fix this is in case we allow entries without a valid IP * address but with a pre-set QOS, e.g. a VC on a given PVC with an * unknown remote end. */ entry->qos = entry->itf->qos; adjust_qos(entry->itf,&entry->qos,0); Q_INSERT_HEAD(itf->table,entry); } if (entry->itf != itf) diag(COMPONENT,DIAG_ERROR,"interesting, interface has changed ... " "(%d -> %d)",entry->itf->number,itf->number); if (addr) { if (!entry->addr) entry->addr = alloc(sizeof(*addr)); *entry->addr = *addr; if (merge) { ENTRY *incoming; while ((incoming = lookup_incoming(addr))) { STOP_TIMER(incoming); Q_REMOVE(unknown_incoming,incoming); incoming->vccs->entry = entry; Q_INSERT_HEAD(entry->vccs,incoming->vccs); set_sndbuf(incoming->vccs); free(incoming); } } } for (walk = entry->vccs; walk; walk = next) { next = walk->next; if (!walk->connecting) if (set_ip(walk->fd,ip) < 0) { diag(COMPONENT,DIAG_ERROR,"set_ip: %s",strerror(errno)); disconnect_vcc(walk); if (walk == vcc) result = -1; } } if (entry->state != as_valid) { if (!entry->vccs && itf->arp_srv && !(entry->flags & ATF_NOVC)) connect_me(entry); send_notifications(entry,1); } if ((entry->flags & ATF_ARPSRV) || !(entry->flags & ATF_PERM)) { if (entry->itf->arp_srv) START_TIMER(entry,CREVAL); else START_TIMER(entry,SREVAL); } entry->state = as_valid; return result; }