/** Create ip_address out of xfrm_address_t. * * @param family * @param src xfrm formatted IP address * @param dst ip_address formatted destination * @return err_t NULL if okay, otherwise an error */ static err_t xfrm_to_ip_address(unsigned family, const xfrm_address_t *src, ip_address *dst) { switch (family) { case AF_INET: /* IPv4 */ initaddr((const void *) &src->a4, sizeof(src->a4), family, dst); return NULL; case AF_INET6: /* IPv6 */ initaddr((const void *) &src->a6, sizeof(src->a6), family, dst); return NULL; default: return "unknown address family"; } }
/* - anyaddr - initialize to the any-address value */ err_t anyaddr(int af, ip_address * dst) { uint32_t v4any = htonl(INADDR_ANY); switch (af) { case AF_INET: return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst); break; case AF_INET6: return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst); break; default: return "unknown address family in anyaddr/unspecaddr"; break; } }
int starter_iface_find(char *iface, int af, ip_address *dst, ip_address *nh) { char *phys; struct ifreq req; struct sockaddr_in *sa = (struct sockaddr_in *)(&req.ifr_addr); int sock; if (!iface) return -1; sock = socket(af, SOCK_DGRAM, 0); if (sock < 0) return -1; phys = _find_physical_iface(sock, iface); if (!phys) goto failed; strncpy(req.ifr_name, phys, IFNAMSIZ); if (ioctl(sock, SIOCGIFFLAGS, &req)!=0) goto failed; if (!(req.ifr_flags & IFF_UP)) goto failed; if ((req.ifr_flags & IFF_POINTOPOINT) && nh && ioctl(sock, SIOCGIFDSTADDR, &req) == 0) { if (sa->sin_family == af) initaddr((const void *)&sa->sin_addr, sizeof(struct in_addr), af, nh); } if ((dst) && (ioctl(sock, SIOCGIFADDR, &req) == 0)) { if (sa->sin_family == af) initaddr((const void *)&sa->sin_addr, sizeof(struct in_addr), af, dst); } close(sock); return 0; failed: close(sock); return -1; }
int open_clientsock(char * address, int port) { struct sockaddr_in servadr; int client_handle; /* Create a new socket */ if ((client_handle = socket (AF_INET, SOCK_STREAM, 0)) == -1) exit_fatal ("Error opening socket Abort !"); /* Now set the server address struct and connect client socket to the port*/ initaddr (&servadr,address,port); if (connect(client_handle,(struct sockaddr *) &servadr, sizeof (struct sockaddr)) == -1) exit_fatal ("connect failed Abort !"); return client_handle; }
int open_sock (int port) { struct sockaddr_in servadr; int server_handle; int O_on = 1; /* Create a new socket */ if ((server_handle = socket (AF_INET, SOCK_STREAM, 0)) == -1) exit_fatal ("Error opening socket Abort !"); if (setsockopt (server_handle, SOL_SOCKET, SO_REUSEADDR, &O_on, sizeof (int)) == -1) exit_fatal ("Setting reused address fail Abort !"); /* Now set the server address struct and bind socket to the port*/ initaddr (&servadr,NULL, port); if (bind (server_handle, (struct sockaddr *) &servadr, sizeof (struct sockaddr)) == -1) exit_fatal ("error bind socket"); /* Listen on the socket */ if (listen (server_handle, MAXCONNECT) == -1) exit_fatal ("Damned errors when listen Abort !"); return server_handle; }
void recv_pcap_packet_gen(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { struct msg_digest *md; u_int32_t *dlt; struct iphdr *ip; struct udphdr *udp; u_char *ike; const struct iface_port *ifp = &if1; int packet_len; err_t from_ugh; union { struct sockaddr sa; struct sockaddr_in sa_in4; struct sockaddr_in6 sa_in6; } from; md = alloc_md(); dlt = (u_int32_t *)bytes; if (*dlt != PF_INET) return; ip = (struct iphdr *)(dlt + 1); udp = (struct udphdr *)(dlt + ip->ihl + 1); ike = (u_char *)(udp + 1); from.sa_in4.sin_addr.s_addr = ip->saddr; from.sa_in4.sin_port = udp->source; md->iface = ifp; packet_len = h->len - (ike - bytes); happy(anyaddr(addrtypeof(&ifp->ip_addr), &md->sender)); from_ugh = initaddr((void *) &from.sa_in4.sin_addr, sizeof(from.sa_in4.sin_addr), AF_INET, &md->sender); setportof(from.sa_in4.sin_port, &md->sender); md->sender_port = ntohs(from.sa_in4.sin_port); cur_from = &md->sender; cur_from_port = md->sender_port; /* Clone actual message contents * and set up md->packet_pbs to describe it. */ init_pbs(&md->packet_pbs, clone_bytes(ike, packet_len, "message buffer in comm_handle()"), packet_len, "packet"); DBG_log("*received %d bytes from %s:%u on %s (port=%d)", (int) pbs_room(&md->packet_pbs), ip_str(&md->sender), (unsigned) md->sender_port, ifp->ip_dev->id_rname, ifp->port); DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs)); process_packet(&md); if (md != NULL) release_md(md); cur_state = NULL; reset_cur_connection(); cur_from = NULL; }
struct raw_iface * find_raw_ifaces4(void) { static const int on = TRUE; /* by-reference parameter; constant, we hope */ int j; /* index into buf */ static int num=64; /* number of interfaces */ struct ifconf ifconf; struct ifreq *buf; /* for list of interfaces -- arbitrary limit */ struct raw_iface *rifaces = NULL; int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */ /* get list of interfaces with assigned IPv4 addresses from system */ if (master_sock == -1) exit_log_errno((e, "socket() failed in find_raw_ifaces4()")); if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR , (const void *)&on, sizeof(on)) < 0) exit_log_errno((e, "setsockopt() in find_raw_ifaces4()")); /* bind the socket */ { ip_address any; happy(anyaddr(AF_INET, &any)); setportof(htons(pluto_port), &any); if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0) exit_log_errno((e, "bind() failed in find_raw_ifaces4()")); } buf = NULL; /* a million interfaces is probably the maximum, ever... */ while(num < (1024*1024)) { /* Get local interfaces. See netdevice(7). */ ifconf.ifc_len = num * sizeof(struct ifreq); buf = (void *) realloc(buf, ifconf.ifc_len); if (!buf) exit_log_errno((e, "realloc of %d in find_raw_ifaces4()", ifconf.ifc_len)); memset(buf, 0, num*sizeof(struct ifreq)); ifconf.ifc_buf = (void *) buf; if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); /* if we got back less than we asked for, we have them all */ if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num)) break; /* try again and ask for more this time */ num *= 2; } /* Add an entry to rifaces for each interesting interface. */ for (j = 0; (j+1) * sizeof(struct ifreq) <= (size_t)ifconf.ifc_len; j++) { struct raw_iface ri; const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr; struct ifreq auxinfo; /* ignore all but AF_INET interfaces */ if (rs->sin_family != AF_INET) continue; /* not interesting */ /* build a NUL-terminated copy of the rname field */ memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ); ri.name[IFNAMSIZ] = '\0'; /* ignore if our interface names were specified, and this isn't one */ if (pluto_ifn_roof != 0) { int i; for (i = 0; i != pluto_ifn_roof; i++) if (streq(ri.name, pluto_ifn[i])) break; if (i == pluto_ifn_roof) continue; /* not found -- skip */ } /* Find out stuff about this interface. See netdevice(7). */ zero(&auxinfo); /* paranoia */ memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ); if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) exit_log_errno((e , "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()" , ri.name)); if (!(auxinfo.ifr_flags & IFF_UP)) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is not up" , ri.name)); continue; /* ignore an interface that isn't UP */ } if (auxinfo.ifr_flags & IFF_SLAVE) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is a slave interface" , ri.name)); continue; /* ignore slave interfaces; they share IPs with their master */ } /* ignore unconfigured interfaces */ if (rs->sin_addr.s_addr == 0) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is unconfigured" , ri.name)); continue; } happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr) , AF_INET, &ri.addr)); DBG(DBG_CONTROL, DBG_log("found %s with address %s" , ri.name, ip_str(&ri.addr))); ri.next = rifaces; rifaces = clone_thing(ri, "struct raw_iface"); } close(master_sock); return rifaces; }
err_t parse_redirect_payload(pb_stream *input_pbs, const char *allowed_targets_list, const chunk_t *nonce, ip_address *redirect_ip /* result */) { struct ikev2_redirect_part gw_info; if (!in_struct(&gw_info, &ikev2_redirect_desc, input_pbs, NULL)) return "received deformed REDIRECT payload"; int af; switch (gw_info.gw_identity_type) { case GW_IPV4: af = AF_INET; break; case GW_IPV6: af = AF_INET6; break; case GW_FQDN: af = AF_UNSPEC; break; default: return "bad GW Ident Type"; } /* in_raw() actual GW Identity */ switch (af) { case AF_UNSPEC: { /* * The FQDN string isn't NUL-terminated. * * The length is stored in a byte so it cannot be * larger than 0xFF. * Some helpful compilers moan about this test being always true * so I eliminated it: * passert(gw_info.gw_identity_len <= 0xFF); */ unsigned char gw_str[0xFF]; if (!in_raw(&gw_str, gw_info.gw_identity_len, input_pbs, "GW Identity")) return "error while extracting GW Identity from variable part of IKEv2_REDIRECT Notify payload"; err_t ugh = ttoaddr((char *) gw_str, gw_info.gw_identity_len, AF_UNSPEC, redirect_ip); if (ugh != NULL) return ugh; break; } case AF_INET: case AF_INET6: { if (pbs_left(input_pbs) < gw_info.gw_identity_len) return "variable part of payload is smaller than transfered GW Identity Length"; /* parse address directly to redirect_ip */ err_t ugh = initaddr(input_pbs->cur, gw_info.gw_identity_len, af, redirect_ip); if (ugh != NULL) return ugh; DBG(DBG_PARSING, { ip_address_buf b; DBG_log(" GW Identity IP: %s", ipstr(redirect_ip, &b)); }); input_pbs->cur += gw_info.gw_identity_len; break; } }
struct raw_iface *find_raw_ifaces4(void) { static const int on = TRUE; /* by-reference parameter; constant, we hope */ int j; /* index into buf */ struct ifconf ifconf; struct ifreq *buf = NULL; /* for list of interfaces -- arbitrary limit */ struct ifreq *bp; /* cursor into buf */ struct raw_iface *rifaces = NULL; int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */ /* * Current upper bound on number of interfaces. * Tricky: because this is a static, we won't have to start from * 64 in subsequent calls. */ static int num = 64; /* number of interfaces */ /* get list of interfaces with assigned IPv4 addresses from system */ if (master_sock == -1) exit_log_errno((e, "socket() failed in find_raw_ifaces4()")); if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0) exit_log_errno((e, "setsockopt() in find_raw_ifaces4()")); /* bind the socket */ { ip_address any; happy(anyaddr(AF_INET, &any)); setportof(htons(pluto_port), &any); if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0) exit_log_errno((e, "bind() failed in find_raw_ifaces4()")); } /* a million interfaces is probably the maximum, ever... */ for (; num < (1024 * 1024); num *= 2) { /* Get num local interfaces. See netdevice(7). */ ifconf.ifc_len = num * sizeof(struct ifreq); buf = realloc(buf, ifconf.ifc_len); if (buf == NULL) { exit_log_errno((e, "realloc of %d in find_raw_ifaces4()", ifconf.ifc_len)); } memset(buf, 0xDF, ifconf.ifc_len); /* stomp */ ifconf.ifc_buf = (void *) buf; if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); /* if we got back less than we asked for, we have them all */ if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num)) break; } /* Add an entry to rifaces for each interesting interface. On Apple, the size of struct ifreq depends on the contents of the union. See if.h */ for (bp = buf, j = 0; bp < (unsigned char *)buf + (size_t)ifconf.ifc_len; bp = (struct ifreq *) ((unsigned char *)bp +_SIZEOF_ADDR_IFREQ(*bp)), j++) { struct raw_iface ri; const struct sockaddr_in *rs = (struct sockaddr_in *) &bp->ifr_addr; struct ifreq auxinfo; /* ignore all but AF_INET interfaces */ if (rs->sin_family != AF_INET) continue; /* not interesting */ /* build a NUL-terminated copy of the rname field */ memcpy(ri.name, bp->ifr_name, IFNAMSIZ); ri.name[IFNAMSIZ] = '\0'; /* ignore if our interface names were specified, and this isn't one */ if (pluto_ifn_roof != 0) { int i; for (i = 0; i != pluto_ifn_roof; i++) if (streq(ri.name, pluto_ifn[i])) break; if (i == pluto_ifn_roof) continue; /* not found -- skip */ } /* Find out stuff about this interface. See netdevice(7). */ zero(&auxinfo); /* paranoia */ memcpy(auxinfo.ifr_name, bp->ifr_name, IFNAMSIZ); if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) { exit_log_errno((e, "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()", ri.name)); } if (!(auxinfo.ifr_flags & IFF_UP)) continue; /* ignore an interface that isn't UP */ /* ignore unconfigured interfaces */ if (rs->sin_addr.s_addr == 0) continue; happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr), AF_INET, &ri.addr)); DBG(DBG_CONTROL, { ipstr_buf b; DBG_log("found %s with address %s", ri.name, ipstr(&ri.addr, &b)); }); ri.next = rifaces; rifaces = clone_thing(ri, "struct raw_iface"); }
/* * Process an incoming DAG Advertisement Object. * the DAO is the upward announcement. * */ void dag_network::receive_dao(network_interface *iface, struct in6_addr from, struct in6_addr ip6_to, const time_t now, const struct nd_rpl_dao *dao, unsigned char *data, int dao_len) { /* it has already been checked to be at least sizeof(*dio) */ //int dao_payload_len = dao_len - sizeof(*dao); /* increment stat of number of packets processed */ this->mStats[PS_PACKET_RECEIVED]++; this->mStats[PS_DAO_PACKET_RECEIVED]++; /* validate this packet, if possible */ bool secure = this->check_security(dao, dao_len); rpl_node *peer; /* find the node entry from this source IP, and update seen time */ /* this will create the node if it does not already exist! */ if((peer = this->update_child(iface, from, ip6_to, now)) == NULL) { return; } if(mActive == false) { this->mStats[PS_PACKETS_WATCHED]++; return; } /* look for the suboptions, process them */ rpl_dao decoded_dao(data, dao_len, this); unsigned int addrcount = 0; struct rpl_dao_target *rpltarget; while((rpltarget = decoded_dao.rpltarget()) != NULL) { char addrfound[SUBNETTOT_BUF]; unsigned char v6bytes[16]; int prefixbytes = ((rpltarget->rpl_dao_prefixlen+7) / 8); ip_subnet prefix; prefix.maskbits = rpltarget->rpl_dao_prefixlen; memset(v6bytes, 0, 16); memcpy(v6bytes, rpltarget->rpl_dao_prefix, prefixbytes); initaddr(v6bytes, 16, AF_INET6, &prefix.addr); addrcount++; subnettot(&prefix, 0, addrfound, sizeof(addrfound)); /* need to look at dag_members, and see if the child node already * exists, and add if not */ debug->verbose(" recv DAO rpltarget re: network %s, target %s (added)\n", addrfound, peer->node_name()); add_childnode(peer, iface, prefix); } maybe_send_dao(); /* now send a DAO-ACK back this the node, using the interface it arrived on, if asked to. */ if(RPL_DAO_K(dao->rpl_flags)) { debug->verbose("sending DAOACK about %u networks, to %s\n", addrcount, peer->node_name()); iface->send_daoack(*peer, *this, dao->rpl_daoseq); } /* increment stat of number of packets processed */ this->mStats[PS_PACKET_PROCESSED]++; }
void dag_network::potentially_lower_rank(rpl_node &peer, network_interface *iface, const struct nd_rpl_dio *dio, int dio_len) { unsigned int rank = ntohs(dio->rpl_dagrank); debug->verbose(" does peer '%s' have better rank? (%u < %u)\n", peer.node_name(), rank, mBestRank); this->mStats[PS_LOWER_RANK_CONSIDERED]++; if(rank > mBestRank) { this->mStats[PS_LOWER_RANK_REJECTED]++; return; } debug->verbose(" Yes, '%s' has best rank %u\n", peer.node_name(), rank); if(dag_bestparent == &peer || dag_parent == &peer) { debug->verbose(" But it is the same parent as before: ignored\n"); this->mStats[PS_SAME_PARENT_IGNORED]++; return; } /* XXX * this is actually quite a big deal (SEE rfc6550), setting my RANK. * just fake it for now by adding 1. */ if(mDTSN != INVALID_SEQUENCE && mDTSN >= dio->rpl_dtsn) { debug->verbose(" Same sequence number, ignore\n"); this->mStats[PS_SAME_SEQUENCE_IGNORED]++; return; } mDTSN = dio->rpl_dtsn; mBestRank = rank; /* XXX * this is actually quite a big deal (SEE rfc6550), setting my RANK. * just fake it for now by adding 1. */ mMyRank = rank + 1; // XXX mGrounded = RPL_DIO_GROUNDED(dio->rpl_mopprf); mInstanceid = dio->rpl_instanceid; mVersion = dio->rpl_version; mMode = RPL_DIO_MOP(dio->rpl_mopprf); dag_bestparentif = iface; dag_bestparent = &peer; /* now see if we have already an address on this new network */ /* * to do this, we have to crack open the DIO. UP to this point * we haven't taken the DIO apart, so do, keeping stuff on the stack. */ rpl_dio decoded_dio(peer, this, dio, dio_len); unsigned int optcount = 0; struct rpl_dio_destprefix *dp; while((dp = decoded_dio.destprefix()) != NULL) { unsigned char v6bytes[16]; int prefixbytes = ((dp->rpl_dio_prefixlen+7) / 8); ip_subnet prefix; prefix.maskbits = dp->rpl_dio_prefixlen; memset(v6bytes, 0, 16); memcpy(v6bytes, dp->rpl_dio_prefix, prefixbytes); initaddr(v6bytes, 16, AF_INET6, &prefix.addr); optcount++; add_prefix(peer, iface, prefix); } debug->verbose(" processed %u pio options\n", optcount); /* now schedule sending out packets */ if(dag_parent) { /* can only send DIOs once we are sure about our parent! */ maybe_schedule_dio(); } maybe_send_dao(); }