/* checks if the proto: ip:port is one of the address we listen on * and returns the corresponding socket_info structure. * (same as grep_socket_info, but use ip addr instead) * if port==0, the port number is ignored * if proto==0 (PROTO_NONE) the protocol is ignored * returns 0 if not found * WARNING: uses str2ip6 so it will overwrite any previous * unsaved result of this function (static buffer) */ struct socket_info* find_si(struct ip_addr* ip, unsigned short port, unsigned short proto) { struct socket_info* si; struct socket_info** list; unsigned short c_proto; c_proto=proto?proto:PROTO_UDP; do{ /* get the proper sock_list */ if (c_proto==PROTO_NONE) list=&udp_listen; else list=get_sock_info_list(c_proto); if (list==0){ LOG(L_WARN, "WARNING: grep_sock_info: " "unknown proto %d\n", c_proto); goto not_found; /* false */ } for (si=*list; si; si=si->next){ if (port) { if (si->port_no!=port) { continue; } } if (ip_addr_cmp(ip, &si->address)) goto found; } }while( (proto==0) && (c_proto=next_proto(c_proto)) ); not_found: return 0; found: return si; }
/* adds a sock_info structure to the corresponding proto list * return 0 on success, -1 on error */ int add_listen_iface(char* name, unsigned short port, unsigned short proto, enum si_flags flags) { struct socket_info** list; unsigned short c_proto; c_proto=(proto)?proto:PROTO_UDP; do{ list=get_sock_info_list(c_proto); if (list==0){ LOG(L_ERR, "ERROR: add_listen_iface: get_sock_info_list failed\n"); goto error; } if (port==0){ /* use default port */ port= #ifdef USE_TLS ((c_proto)==PROTO_TLS)?tls_port_no: #endif port_no; } #ifdef USE_TLS else if ((c_proto==PROTO_TLS) && (proto==0)){ /* -l ip:port => on udp:ip:port; tcp:ip:port and tls:ip:port+1? */ port++; } #endif if (new_sock2list(name, port, c_proto, flags, list)<0){ LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list failed\n"); goto error; } }while( (proto==0) && (c_proto=next_proto(c_proto))); return 0; error: return -1; }
void print_all_socket_lists() { struct socket_info *si; struct socket_info** list; unsigned short proto; proto=PROTO_UDP; do{ list=get_sock_info_list(proto); for(si=list?*list:0; si; si=si->next){ printf(" %s: %s [%s]:%s%s\n", get_proto_name(proto), si->name.s, si->address_str.s, si->port_no_str.s, si->flags & SI_IS_MCAST ? " mcast" : ""); } }while((proto=next_proto(proto))); }
/* * RPC command to list the listening sockets */ static void corex_rpc_list_sockets(rpc_t* rpc, void* ctx) { void* th; void* ih; struct socket_info *si; struct socket_info** list; struct addr_info* ai; unsigned short proto; proto=PROTO_UDP; do { list=get_sock_info_list(proto); for(si=list?*list:0; si; si=si->next) { /* add structure node */ if (rpc->add(ctx, "{", &th) < 0) { rpc->fault(ctx, 500, "Internal error socket structure"); return; } if(rpc->struct_add(th, "ss{", "PROTO", get_valid_proto_name(proto), "NAME", si->name.s, "ADDRLIST", &ih)<0) { rpc->fault(ctx, 500, "Internal error address list structure"); return; } if(rpc->struct_add(ih, "s", "ADDR", si->address_str.s)<0) { rpc->fault(ctx, 500, "Internal error address structure"); return; } if (si->addr_info_lst) { for (ai=si->addr_info_lst; ai; ai=ai->next) { if(rpc->struct_add(ih, "s", "ADDR", ai->address_str.s)<0) { rpc->fault(ctx, 500, "Internal error extra address structure"); return; } } } if(rpc->struct_add(th, "ssss", "PORT", si->port_no_str.s, "MCAST", si->flags & SI_IS_MCAST ? "yes" : "no", "MHOMED", si->flags & SI_IS_MHOMED? "yes" : "no", "ADVERTISE", si->useinfo.name.s?si->useinfo.name.s:"-")<0) { rpc->fault(ctx, 500, "Internal error attrs structure"); return; } } } while((proto=next_proto(proto))); return; }
/* checks if the proto: host:port is one of the address we listen on * and returns the corresponding socket_info structure. * if port==0, the port number is ignored * if proto==0 (PROTO_NONE) the protocol is ignored * returns 0 if not found * WARNING: uses str2ip6 so it will overwrite any previous * unsaved result of this function (static buffer) */ struct socket_info* grep_sock_info(str* host, unsigned short port, unsigned short proto) { char* hname; int h_len; struct socket_info* si; struct socket_info** list; unsigned short c_proto; #ifdef USE_IPV6 struct ip_addr* ip6; #endif h_len=host->len; hname=host->s; #ifdef USE_IPV6 if ((h_len>2)&&((*hname)=='[')&&(hname[h_len-1]==']')){ /* ipv6 reference, skip [] */ hname++; h_len-=2; } #endif c_proto=proto?proto:PROTO_UDP; do{ /* get the proper sock_list */ if (c_proto==PROTO_NONE) list=&udp_listen; else list=get_sock_info_list(c_proto); if (list==0){ LOG(L_WARN, "WARNING: grep_sock_info: " "unknown proto %d\n", c_proto); goto not_found; /* false */ } for (si=*list; si; si=si->next){ DBG("grep_sock_info - checking if host==us: %d==%d && " " [%.*s] == [%.*s]\n", h_len, si->name.len, h_len, hname, si->name.len, si->name.s ); if (port) { DBG("grep_sock_info - checking if port %d matches port %d\n", si->port_no, port); if (si->port_no!=port) { continue; } } if ( (h_len==si->name.len) && (strncasecmp(hname, si->name.s, si->name.len)==0) /*slower*/) /* comp. must be case insensitive, host names * can be written in mixed case, it will also match * ipv6 addresses if we are lucky*/ goto found; /* check if host == ip address */ #ifdef USE_IPV6 /* ipv6 case is uglier, host can be [3ffe::1] */ ip6=str2ip6(host); if (ip6){ if (ip_addr_cmp(ip6, &si->address)) goto found; /* match */ else continue; /* no match, but this is an ipv6 address so no point in trying ipv4 */ } #endif /* ipv4 */ if ( (!(si->flags&SI_IS_IP)) && (h_len==si->address_str.len) && (memcmp(hname, si->address_str.s, si->address_str.len)==0) ) goto found; } }while( (proto==0) && (c_proto=next_proto(c_proto)) ); not_found: return 0; found: return si; }