/* - ttosubnet - convert text "addr/mask" to address and mask * Mask can be integer bit count. */ err_t ttosubnet(const char *src, size_t srclen,int af,ip_subnet *dst) { const char *slash; const char *colon; const char *mask; size_t mlen; const char *oops; unsigned long bc; static char def[] = DEFAULTSUBNET; # define DEFLEN (sizeof(def) - 1) /* -1 for NUL */ static char defis4[] = "0/0"; # define DEFIS4LEN (sizeof(defis4) - 1) static char defis6[] = "::/0"; # define DEFIS6LEN (sizeof(defis6) - 1) ip_address addrtmp; ip_address masktmp; int nbits; int i; if (srclen == 0) srclen = strlen(src); if (srclen == 0) return "empty string"; switch (af) { case AF_INET: nbits = 32; break; case AF_INET6: nbits = 128; break; default: return "unknown address family in ttosubnet"; break; } if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) { src = (af == AF_INET) ? defis4 : defis6; srclen = (af == AF_INET) ? DEFIS4LEN : DEFIS6LEN; } slash = memchr(src, '/', srclen); if (slash == NULL) return "no / in subnet specification"; mask = slash + 1; mlen = srclen - (mask - src); oops = ttoaddr(src, slash-src, af, &addrtmp); if (oops != NULL) return oops; /* extract port, as last : */ colon = memchr(mask, ':', mlen); if (colon == 0) { setportof(0, &addrtmp); } else { unsigned long port; oops = ttoul(colon+1, mlen-(colon-mask+1), 0, &port); if (oops != NULL) return oops; setportof(htons(port), &addrtmp); mlen = colon - mask; } /*extract mask */ oops = ttoul(mask, mlen, 10, &bc); if (oops == NULL) { /* ttoul succeeded, it's a bit-count mask */ if (bc > nbits) return "subnet mask bit count too large"; i = bc; } else if(af == AF_INET) { oops = ttoaddr(mask, mlen, af, &masktmp); if (oops != NULL) return oops; i = masktocount(&masktmp); if (i < 0) return "non-contiguous or otherwise erroneous mask"; } else { return "masks are not permitted for IPv6 addresses"; } return initsubnet(&addrtmp, i, '0', dst); }
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; }
static void bsdkame_process_raw_ifaces(struct raw_iface *rifaces) { struct raw_iface *ifp; /* * There are no virtual interfaces, so all interfaces are valid */ for (ifp = rifaces; ifp != NULL; ifp = ifp->next) { bool after = FALSE; /* has vfp passed ifp on the list? */ bool bad = FALSE; struct raw_iface *vfp; for (vfp = rifaces; vfp != NULL; vfp = vfp->next) { if (vfp == ifp) { after = TRUE; } else if (sameaddr(&ifp->addr, &vfp->addr)) { if (after) { loglog(RC_LOG_SERIOUS , "IP interfaces %s and %s share address %s!" , ifp->name, vfp->name, ip_str(&ifp->addr)); } bad = TRUE; } } if (bad) continue; /* We've got all we need; see if this is a new thing: * search old interfaces list. */ { struct iface_port **p = &interfaces; for (;;) { struct iface_port *q = *p; struct iface_dev *id = NULL; /* search is over if at end of list */ if (q == NULL) { /* matches nothing -- create a new entry */ int fd = create_socket(ifp, ifp->name, pluto_port); if (fd < 0) break; #ifdef NAT_TRAVERSAL if (nat_traversal_support_non_ike && addrtypeof(&ifp->addr) == AF_INET) { nat_traversal_espinudp_socket(fd, "IPv4", ESPINUDP_WITH_NON_IKE); } #endif q = alloc_thing(struct iface_port, "struct iface_port"); id = alloc_thing(struct iface_dev, "struct iface_dev"); LIST_INSERT_HEAD(&interface_dev, id, id_entry); q->ip_dev = id; id->id_rname = clone_str(ifp->name, "real device name"); id->id_vname = clone_str(ifp->name, "virtual device name"); id->id_count++; q->ip_addr = ifp->addr; q->fd = fd; q->next = interfaces; q->change = IFN_ADD; q->port = pluto_port; q->ike_float = FALSE; interfaces = q; openswan_log("adding interface %s/%s %s:%d" , q->ip_dev->id_vname , q->ip_dev->id_rname , ip_str(&q->ip_addr) , q->port); #ifdef NAT_TRAVERSAL /* * right now, we do not support NAT-T on IPv6, because * the kernel did not support it, and gave an error * it one tried to turn it on. */ if (nat_traversal_support_port_floating && addrtypeof(&ifp->addr) == AF_INET) { fd = create_socket(ifp, id->id_vname, NAT_T_IKE_FLOAT_PORT); if (fd < 0) break; nat_traversal_espinudp_socket(fd, "IPv4" , ESPINUDP_WITH_NON_ESP); q = alloc_thing(struct iface_port, "struct iface_port"); q->ip_dev = id; id->id_count++; q->ip_addr = ifp->addr; setportof(htons(NAT_T_IKE_FLOAT_PORT), &q->ip_addr); q->port = NAT_T_IKE_FLOAT_PORT; q->fd = fd; q->next = interfaces; q->change = IFN_ADD; q->ike_float = TRUE; interfaces = q; openswan_log("adding interface %s/%s %s:%d" , q->ip_dev->id_vname, q->ip_dev->id_rname , ip_str(&q->ip_addr) , q->port); } #endif break; } /* search over if matching old entry found */ if (streq(q->ip_dev->id_rname, ifp->name) && streq(q->ip_dev->id_vname, ifp->name) && sameaddr(&q->ip_addr, &ifp->addr)) { /* matches -- rejuvinate old entry */ q->change = IFN_KEEP; #ifdef NAT_TRAVERSAL /* look for other interfaces to keep (due to NAT-T) */ for (q = q->next ; q ; q = q->next) { if (streq(q->ip_dev->id_rname, ifp->name) && streq(q->ip_dev->id_vname, ifp->name) && sameaddr(&q->ip_addr, &ifp->addr)) { q->change = IFN_KEEP; } } #endif break; } /* try again */ p = &q->next; } /* for (;;) */ }
static void klips_process_raw_ifaces(struct raw_iface *rifaces) { struct raw_iface *ifp; /* Find all virtual/real interface pairs. * For each real interface... */ for (ifp = rifaces; ifp != NULL; ifp = ifp->next) { struct raw_iface *v = NULL; /* matching ipsecX interface */ struct raw_iface fake_v; bool after = FALSE; /* has vfp passed ifp on the list? */ bool bad = FALSE; struct raw_iface *vfp; ip_address lip; if (pluto_listen) { err_t e; e = ttoaddr(pluto_listen, 0, 0, &lip); if (e) { DBG_log("invalid listen= option ignored: %s\n", e); pluto_listen = NULL; } } /* ignore if virtual (ipsec*) interface */ if (strncmp(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX) - 1) == 0) continue; /* ignore if virtual (mast*) interface */ if (strncmp(ifp->name, MASTDEVPREFIX, sizeof(MASTDEVPREFIX) - 1) == 0) continue; for (vfp = rifaces; vfp != NULL; vfp = vfp->next) { if (vfp == ifp) { after = TRUE; } else if (sameaddr(&ifp->addr, &vfp->addr)) { /* Different entries with matching IP addresses. * Many interesting cases. */ if (strncmp(vfp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX) - 1) == 0) { if (v != NULL) { loglog(RC_LOG_SERIOUS, "ipsec interfaces %s and %s share same address %s", v->name, vfp->name, ip_str(&ifp->addr)); bad = TRUE; } else { v = vfp; /* current winner */ } } else { /* ugh: a second real interface with the same IP address * "after" allows us to avoid double reporting. */ #if defined(linux) && defined(NETKEY_SUPPORT) if (kern_interface == USE_NETKEY) { if (after) { bad = TRUE; break; } continue; } #endif if (after) { loglog(RC_LOG_SERIOUS, "IP interfaces %s and %s share address %s!", ifp->name, vfp->name, ip_str(&ifp->addr)); } bad = TRUE; } } } if (bad) continue; #if defined(linux) && defined(NETKEY_SUPPORT) if (kern_interface == USE_NETKEY) { v = ifp; goto add_entry; } #endif /* what if we didn't find a virtual interface? */ if (v == NULL) { if (kern_interface == NO_KERNEL) { /* kludge for testing: invent a virtual device */ static const char fvp[] = "virtual"; fake_v = *ifp; passert(sizeof(fake_v.name) > sizeof(fvp)); strcpy(fake_v.name, fvp); addrtot(&ifp->addr, 0, fake_v.name + sizeof(fvp) - 1, sizeof(fake_v.name) - (sizeof(fvp) - 1)); v = &fake_v; } else { DBG(DBG_CONTROL, DBG_log( "IP interface %s %s has no matching ipsec* interface -- ignored", ifp->name, ip_str(&ifp->addr))); continue; } } /* ignore if --listen is specified and we do not match */ if (pluto_listen != NULL) { if (!sameaddr(&lip, &ifp->addr)) { libreswan_log("skipping interface %s with %s", ifp->name, ip_str(&ifp->addr)); continue; } } /* We've got all we need; see if this is a new thing: * search old interfaces list. */ #if defined(linux) && defined(NETKEY_SUPPORT) add_entry: #endif { struct iface_port **p = &interfaces; for (;; ) { struct iface_port *q = *p; struct iface_dev *id = NULL; /* search is over if at end of list */ if (q == NULL) { /* matches nothing -- create a new entry */ int fd = create_socket(ifp, v->name, pluto_port); if (fd < 0) break; DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: checking for nat_traversal_support_non_ike for IPv4")); if (nat_traversal_support_non_ike && addrtypeof(&ifp->addr) == AF_INET) { DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: found, calling nat_traversal_espinudp_socket")); nat_traversal_espinudp_socket( fd, "IPv4", ESPINUDP_WITH_NON_IKE); } else { DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: support not found, nat_traversal_support_non_ike = %s", nat_traversal_support_non_ike ? "TRUE" : "FALSE")); } q = alloc_thing(struct iface_port, "struct iface_port"); id = alloc_thing(struct iface_dev, "struct iface_dev"); LIST_INSERT_HEAD(&interface_dev, id, id_entry); q->ip_dev = id; id->id_rname = clone_str(ifp->name, "real device name"); id->id_vname = clone_str(v->name, "virtual device name klips"); id->id_count++; q->ip_addr = ifp->addr; q->fd = fd; q->next = interfaces; q->change = IFN_ADD; q->port = pluto_port; q->ike_float = FALSE; interfaces = q; libreswan_log( "adding interface %s/%s %s:%d", q->ip_dev->id_vname, q->ip_dev->id_rname, ip_str(&q->ip_addr), q->port); /* * right now, we do not support NAT-T on IPv6, because * the kernel did not support it, and gave an error * it one tried to turn it on. */ if (nat_traversal_support_port_floating && addrtypeof(&ifp->addr) == AF_INET) { DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: found floating port, calling nat_traversal_espinudp_socket")); fd = create_socket(ifp, v->name, pluto_natt_float_port); if (fd < 0) break; nat_traversal_espinudp_socket( fd, "IPv4", ESPINUDP_WITH_NON_ESP); q = alloc_thing( struct iface_port, "struct iface_port"); q->ip_dev = id; id->id_count++; q->ip_addr = ifp->addr; setportof(htons( pluto_natt_float_port), &q->ip_addr); q->port = pluto_natt_float_port; q->fd = fd; q->next = interfaces; q->change = IFN_ADD; q->ike_float = TRUE; interfaces = q; libreswan_log( "adding interface %s/%s %s:%d", q->ip_dev->id_vname, q->ip_dev->id_rname, ip_str(&q-> ip_addr), q->port); } break; } /* search over if matching old entry found */ if (streq(q->ip_dev->id_rname, ifp->name) && streq(q->ip_dev->id_vname, v->name) && sameaddr(&q->ip_addr, &ifp->addr)) { /* matches -- rejuvinate old entry */ q->change = IFN_KEEP; /* look for other interfaces to keep (due to NAT-T) */ for (q = q->next; q; q = q->next) { if (streq(q->ip_dev->id_rname, ifp->name) && streq(q->ip_dev->id_vname, v->name) && sameaddr(&q->ip_addr, &ifp->addr)) q->change = IFN_KEEP; } break; } /* try again */ p = &q->next; } /* for (;;) */ }
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"); }