int pico_frame_dst_is_unicast(struct pico_frame *f) { if (0) { return 0; } #ifdef PICO_SUPPORT_IPV4 if (IS_IPV4(f)) { struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr; if (pico_ipv4_is_multicast(hdr->dst.addr) || pico_ipv4_is_broadcast(hdr->dst.addr)) return 0; return 1; } #endif #ifdef PICO_SUPPORT_IPV6 if (IS_IPV6(f)) { struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr; if (pico_ipv6_is_multicast(hdr->dst.addr) || pico_ipv6_is_unspecified(hdr->dst.addr)) return 0; return 1; } #endif else return 0; }
void pico_store_network_origin(void *src, struct pico_frame *f) { #ifdef PICO_SUPPORT_IPV4 struct pico_ip4 *ip4; #endif #ifdef PICO_SUPPORT_IPV6 struct pico_ip6 *ip6; #endif #ifdef PICO_SUPPORT_IPV4 if (IS_IPV4(f)) { struct pico_ipv4_hdr *hdr; hdr = (struct pico_ipv4_hdr *) f->net_hdr; ip4 = (struct pico_ip4 *) src; ip4->addr = hdr->src.addr; } #endif #ifdef PICO_SUPPORT_IPV6 if (IS_IPV6(f)) { struct pico_ipv6_hdr *hdr; hdr = (struct pico_ipv6_hdr *) f->net_hdr; ip6 = (struct pico_ip6 *) src; memcpy(ip6->addr, hdr->src.addr, PICO_SIZE_IP6); } #endif }
/* * Calculate the reference id from the address. If it is an IPv4 * address, use it as is. If it is an IPv6 address, do a md5 on * it and use the bottom 4 bytes. * The result is in network byte order. */ u_int32 addr2refid(sockaddr_u *addr) { u_char digest[20]; u_int32 addr_refid; EVP_MD_CTX ctx; u_int len; if (IS_IPV4(addr)) return (NSRCADR(addr)); INIT_SSL(); #if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL EVP_MD_CTX_init(&ctx); #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW /* MD5 is not used as a crypto hash here. */ EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); #endif if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) { msyslog(LOG_ERR, "MD5 init failed"); exit(1); } #else EVP_DigestInit(&ctx, EVP_md5()); #endif EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr), sizeof(struct in6_addr)); EVP_DigestFinal(&ctx, digest, &len); memcpy(&addr_refid, digest, sizeof(addr_refid)); return (addr_refid); }
/* This is called by dev loop in order to ensure correct ethernet addressing. * Returns 0 if the destination is unknown, and -1 if the packet is not deliverable * due to ethernet addressing (i.e., no arp association was possible. * * Only IP packets must pass by this. ARP will always use direct dev->send() function, so * we assume IP is used. */ int32_t pico_ethernet_send(struct pico_frame *f) { const struct pico_eth *dstmac = NULL; int32_t ret = -1; if (IS_IPV6(f)) { /*TODO: Neighbor solicitation */ dstmac = NULL; } else if (IS_IPV4(f)) { if (IS_BCAST(f) || destination_is_bcast(f)) { dstmac = (const struct pico_eth *const) PICO_ETHADDR_ALL; } #ifdef PICO_SUPPORT_MCAST else if (destination_is_mcast(f)) { uint8_t pico_mcast_mac[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; dstmac = pico_ethernet_mcast_translate(f, pico_mcast_mac); } #endif else { dstmac = pico_arp_get(f); if (!dstmac) return 0; } /* This sets destination and source address, then pushes the packet to the device. */ if (dstmac && (f->start > f->buffer) && ((f->start - f->buffer) >= PICO_SIZE_ETHHDR)) { struct pico_eth_hdr *hdr; f->start -= PICO_SIZE_ETHHDR; f->len += PICO_SIZE_ETHHDR; f->datalink_hdr = f->start; hdr = (struct pico_eth_hdr *) f->datalink_hdr; memcpy(hdr->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH); memcpy(hdr->daddr, dstmac, PICO_SIZE_ETH); hdr->proto = PICO_IDETH_IPV4; if(!memcmp(hdr->daddr, hdr->saddr, PICO_SIZE_ETH)) { dbg("sending out packet destined for our own mac\n"); return pico_ethernet_receive(f); } else if(IS_LIMITED_BCAST(f)) { ret = pico_device_broadcast(f); } else { ret = (int32_t)f->dev->send(f->dev, f->start, (int) f->len); /* Frame is discarded after this return by the caller */ } if(!ret) pico_frame_discard(f); return ret; } else { return -1; } } /* End IPV4 ethernet addressing */ return -1; }
/* * restrict_source - maintains dynamic "restrict source ..." entries as * peers come and go. */ void restrict_source( sockaddr_u * addr, int farewell, /* 0 to add, 1 to remove */ u_long expire /* 0 is infinite, valid until */ ) { sockaddr_u onesmask; restrict_u * res; int found_specific; if (!restrict_source_enabled || SOCK_UNSPEC(addr) || IS_MCAST(addr) || ISREFCLOCKADR(addr)) return; REQUIRE(AF_INET == AF(addr) || AF_INET6 == AF(addr)); SET_HOSTMASK(&onesmask, AF(addr)); if (farewell) { hack_restrict(RESTRICT_REMOVE, addr, &onesmask, 0, 0, 0); DPRINTF(1, ("restrict_source: %s removed", stoa(addr))); return; } /* * If there is a specific entry for this address, hands * off, as it is condidered more specific than "restrict * server ...". * However, if the specific entry found is a fleeting one * added by pool_xmit() before soliciting, replace it * immediately regardless of the expire value to make way * for the more persistent entry. */ if (IS_IPV4(addr)) { res = match_restrict4_addr(SRCADR(addr), SRCPORT(addr)); INSIST(res != NULL); found_specific = (SRCADR(&onesmask) == res->u.v4.mask); } else { res = match_restrict6_addr(&SOCK_ADDR6(addr), SRCPORT(addr)); INSIST(res != NULL); found_specific = ADDR6_EQ(&res->u.v6.mask, &SOCK_ADDR6(&onesmask)); } if (!expire && found_specific && res->expire) { found_specific = 0; free_res(res, IS_IPV6(addr)); } if (found_specific) return; hack_restrict(RESTRICT_FLAGS, addr, &onesmask, restrict_source_mflags, restrict_source_flags, expire); DPRINTF(1, ("restrict_source: %s host restriction added\n", stoa(addr))); }
/* * restrictions - return restrictions for this host */ u_short restrictions( sockaddr_u *srcadr ) { restrict_u *match; struct in6_addr *pin6; u_short flags; res_calls++; flags = 0; /* IPv4 source address */ if (IS_IPV4(srcadr)) { /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, * not later!) */ if (IN_CLASSD(SRCADR(srcadr))) return (int)RES_IGNORE; match = match_restrict4_addr(SRCADR(srcadr), SRCPORT(srcadr)); match->count++; /* * res_not_found counts only use of the final default * entry, not any "restrict default ntpport ...", which * would be just before the final default. */ if (&restrict_def4 == match) res_not_found++; else res_found++; flags = match->flags; } /* IPv6 source address */ if (IS_IPV6(srcadr)) { pin6 = PSOCK_ADDR6(srcadr); /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, * not later!) */ if (IN6_IS_ADDR_MULTICAST(pin6)) return (int)RES_IGNORE; match = match_restrict6_addr(pin6, SRCPORT(srcadr)); match->count++; if (&restrict_def6 == match) res_not_found++; else res_found++; flags = match->flags; } return (flags); }
static int32_t pico_ipv4_ethernet_receive(struct pico_frame *f) { if (IS_IPV4(f)) { pico_enqueue(pico_proto_ipv4.q_in, f); } else { (void)pico_icmp4_param_problem(f, 0); pico_frame_discard(f); return -1; } return (int32_t)f->buffer_len; }
int pico_notify_ttl_expired(struct pico_frame *f) { if (0) {} #ifdef PICO_SUPPORT_ICMP4 else if (IS_IPV4(f)) { pico_icmp4_ttl_expired(f); } #endif #ifdef PICO_SUPPORT_ICMP6 else if (IS_IPV6(f)) { pico_icmp6_ttl_expired(f); } #endif return 0; }
int pico_notify_dest_unreachable(struct pico_frame *f) { if (0) {} #ifdef PICO_SUPPORT_ICMP4 else if (IS_IPV4(f)) { pico_icmp4_dest_unreachable(f); } #endif #ifdef PICO_SUPPORT_ICMP6 else if (IS_IPV6(f)) { pico_icmp6_dest_unreachable(f); } #endif return 0; }
int pico_notify_pkt_too_big(struct pico_frame *f) { if (0) {} #ifdef PICO_SUPPORT_ICMP4 else if (IS_IPV4(f)) { pico_icmp4_mtu_exceeded(f); } #endif #ifdef PICO_SUPPORT_ICMP6 else if (IS_IPV6(f)) { pico_icmp6_pkt_too_big(f); } #endif return 0; }
int pico_destination_is_local(struct pico_frame *f) { if (0) { } #ifdef PICO_SUPPORT_IPV4 else if (IS_IPV4(f)) { struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr; if (pico_ipv4_link_find(&hdr->dst)) return 1; } #endif #ifdef PICO_SUPPORT_IPV6 else if (IS_IPV6(f)) { } #endif return 0; }
/* * Calculate the reference id from the address. If it is an IPv4 * address, use it as is. If it is an IPv6 address, do a md5 on * it and use the bottom 4 bytes. * The result is in network byte order. */ u_int32 addr2refid(sockaddr_u *addr) { u_char digest[20]; u_int32 addr_refid; EVP_MD_CTX ctx; u_int len; if (IS_IPV4(addr)) return (NSRCADR(addr)); INIT_SSL(); EVP_DigestInit(&ctx, EVP_get_digestbynid(NID_md5)); EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr), sizeof(struct in6_addr)); EVP_DigestFinal(&ctx, digest, &len); memcpy(&addr_refid, digest, 4); return (addr_refid); }
sockaddr_u * netof( sockaddr_u *hostaddr ) { static sockaddr_u netofbuf[8]; static int next_netofbuf; u_int32 netnum; sockaddr_u * netaddr; netaddr = &netofbuf[next_netofbuf]; next_netofbuf = (next_netofbuf + 1) % COUNTOF(netofbuf); memcpy(netaddr, hostaddr, sizeof(*netaddr)); if (IS_IPV4(netaddr)) { netnum = SRCADR(netaddr); /* * We live in a modern CIDR world where the basement nets, which * used to be class A, are now probably associated with each * host address. So, for class-A nets, all bits are significant. */ if (IN_CLASSC(netnum)) netnum &= IN_CLASSC_NET; else if (IN_CLASSB(netnum)) netnum &= IN_CLASSB_NET; SET_ADDR4(netaddr, netnum); } else if (IS_IPV6(netaddr)) /* assume the typical /64 subnet size */ zero_mem(&NSRCADR6(netaddr)[8], 8); #ifdef DEBUG else { msyslog(LOG_ERR, "netof unknown AF %d", AF(netaddr)); exit(1); } #endif return netaddr; }
int pico_network_receive(struct pico_frame *f) { if (0) {} #ifdef PICO_SUPPORT_IPV4 else if (IS_IPV4(f)) { pico_enqueue(pico_proto_ipv4.q_in, f); } #endif #ifdef PICO_SUPPORT_IPV6 else if (IS_IPV6(f)) { pico_enqueue(pico_proto_ipv6.q_in, f); } #endif else { dbg("Network not found.\n"); pico_frame_discard(f); return -1; } return f->buffer_len; }
int pico_source_is_local(struct pico_frame *f) { if (0) { } #ifdef PICO_SUPPORT_IPV4 else if (IS_IPV4(f)) { struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr; if (hdr->src.addr == PICO_IPV4_INADDR_ANY) return 1; if (pico_ipv4_link_find(&hdr->src)) return 1; } #endif #ifdef PICO_SUPPORT_IPV6 else if (IS_IPV6(f)) { /* XXX */ } #endif return 0; }
/* * findhostaddr - resolve a host name into an address (Or vice-versa) * * Given one of {ce_peeraddr,ce_name}, find the other one. * It returns 1 for "success" and 0 for an uncorrectable failure. * Note that "success" includes try again errors. You can tell that you * got a "try again" since {ce_peeraddr,ce_name} will still be zero. */ static int findhostaddr( struct conf_entry *entry ) { static int eai_again_seen = 0; struct addrinfo *addr; struct addrinfo hints; int again; int error; checkparent(); /* make sure our guy is still running */ if (entry->ce_name != NULL && !SOCK_UNSPEC(&entry->peer_store)) { /* HMS: Squawk? */ msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are defined..."); return 1; } if (entry->ce_name == NULL && SOCK_UNSPEC(&entry->peer_store)) { msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are undefined!"); return 0; } if (entry->ce_name) { DPRINTF(2, ("findhostaddr: Resolving <%s>\n", entry->ce_name)); memset(&hints, 0, sizeof(hints)); hints.ai_family = entry->type; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; /* * If IPv6 is not available look only for v4 addresses */ if (!ipv6_works) hints.ai_family = AF_INET; error = getaddrinfo(entry->ce_name, NULL, &hints, &addr); if (error == 0) { entry->peer_store = *((sockaddr_u *)(addr->ai_addr)); if (IS_IPV4(&entry->peer_store)) { entry->ce_peeraddr = NSRCADR(&entry->peer_store); entry->ce_config.v6_flag = 0; } else { entry->ce_peeraddr6 = SOCK_ADDR6(&entry->peer_store); entry->ce_config.v6_flag = 1; } freeaddrinfo(addr); } } else { DPRINTF(2, ("findhostaddr: Resolving <%s>\n", stoa(&entry->peer_store))); entry->ce_name = emalloc(MAXHOSTNAMELEN); error = getnameinfo((const struct sockaddr *)&entry->peer_store, SOCKLEN(&entry->peer_store), (char *)&entry->ce_name, MAXHOSTNAMELEN, NULL, 0, 0); } if (0 == error) { /* again is our return value, for success it is 1 */ again = 1; DPRINTF(2, ("findhostaddr: %s resolved.\n", (entry->ce_name) ? "name" : "address")); } else { /* * If the resolver failed, see if the failure is * temporary. If so, return success. */ again = 0; switch (error) { case EAI_FAIL: again = 1; break; case EAI_AGAIN: again = 1; eai_again_seen = 1; break; case EAI_NONAME: #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) case EAI_NODATA: #endif msyslog(LOG_ERR, "host name not found%s%s: %s", (EAI_NONAME == error) ? "" : " EAI_NODATA", (eai_again_seen) ? " (permanent)" : "", entry->ce_name); again = !eai_again_seen; break; #ifdef EAI_SYSTEM case EAI_SYSTEM: /* * EAI_SYSTEM means the real error is in errno. We should be more * discriminating about which errno values require retrying, but * this matches existing behavior. */ again = 1; DPRINTF(1, ("intres: EAI_SYSTEM errno %d (%s) means try again, right?\n", errno, strerror(errno))); break; #endif } /* do this here to avoid perturbing errno earlier */ DPRINTF(2, ("intres: got error status of: %d\n", error)); } return again; }
/* Receive data from broadcast. Couldn't finish that. Need to do some digging * here, especially for protocol independence and IPv6 multicast */ int recv_bcst_data ( SOCKET rsock, char *rdata, int rdata_len, sockaddr_u *sas, sockaddr_u *ras ) { char *buf; int btrue = 1; int recv_bytes = 0; int rdy_socks; GETSOCKNAME_SOCKLEN_TYPE ss_len; struct timeval timeout_tv; fd_set bcst_fd; #ifdef MCAST struct ip_mreq mdevadr; TYPEOF_IP_MULTICAST_LOOP mtrue = 1; #endif #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT struct ipv6_mreq mdevadr6; #endif setsockopt(rsock, SOL_SOCKET, SO_REUSEADDR, &btrue, sizeof(btrue)); if (IS_IPV4(sas)) { if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_data: Couldn't bind() address %s:%d.\n", stoa(sas), SRCPORT(sas)); } #ifdef MCAST if (setsockopt(rsock, IPPROTO_IP, IP_MULTICAST_LOOP, &mtrue, sizeof(mtrue)) < 0) { /* some error message regarding setting up multicast loop */ return BROADCAST_FAILED; } mdevadr.imr_multiaddr.s_addr = NSRCADR(sas); mdevadr.imr_interface.s_addr = htonl(INADDR_ANY); if (mdevadr.imr_multiaddr.s_addr == ~(unsigned)0) { if (ENABLED_OPT(NORMALVERBOSE)) { printf("sntp recv_bcst_data: %s:%d is not a broad-/multicast address, aborting...\n", stoa(sas), SRCPORT(sas)); } return BROADCAST_FAILED; } if (setsockopt(rsock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mdevadr, sizeof(mdevadr)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) { buf = ss_to_str(sas); printf("sntp recv_bcst_data: Couldn't add IP membership for %s\n", buf); free(buf); } } #endif /* MCAST */ } #ifdef ISC_PLATFORM_HAVEIPV6 else if (IS_IPV6(sas)) { if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_data: Couldn't bind() address.\n"); } #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT if (setsockopt(rsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &btrue, sizeof (btrue)) < 0) { /* some error message regarding setting up multicast loop */ return BROADCAST_FAILED; } memset(&mdevadr6, 0, sizeof(mdevadr6)); mdevadr6.ipv6mr_multiaddr = SOCK_ADDR6(sas); if (!IN6_IS_ADDR_MULTICAST(&mdevadr6.ipv6mr_multiaddr)) { if (ENABLED_OPT(NORMALVERBOSE)) { buf = ss_to_str(sas); printf("sntp recv_bcst_data: %s is not a broad-/multicast address, aborting...\n", buf); free(buf); } return BROADCAST_FAILED; } if (setsockopt(rsock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mdevadr6, sizeof(mdevadr6)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) { buf = ss_to_str(sas); printf("sntp recv_bcst_data: Couldn't join group for %s\n", buf); free(buf); } } #endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ } #endif /* ISC_PLATFORM_HAVEIPV6 */ FD_ZERO(&bcst_fd); FD_SET(rsock, &bcst_fd); if (ENABLED_OPT(TIMEOUT)) timeout_tv.tv_sec = (int) atol(OPT_ARG(TIMEOUT)); else timeout_tv.tv_sec = 68; /* ntpd broadcasts every 64s */ timeout_tv.tv_usec = 0; rdy_socks = select(rsock + 1, &bcst_fd, 0, 0, &timeout_tv); switch (rdy_socks) { case -1: if (ENABLED_OPT(NORMALVERBOSE)) perror("sntp recv_bcst_data: select()"); return BROADCAST_FAILED; break; case 0: if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_data: select() reached timeout (%u sec), aborting.\n", (unsigned)timeout_tv.tv_sec); return BROADCAST_FAILED; break; default: ss_len = sizeof(*ras); recv_bytes = recvfrom(rsock, rdata, rdata_len, 0, &ras->sa, &ss_len); break; } if (recv_bytes == -1) { if (ENABLED_OPT(NORMALVERBOSE)) perror("sntp recv_bcst_data: recvfrom:"); recv_bytes = BROADCAST_FAILED; } #ifdef MCAST if (IS_IPV4(sas)) setsockopt(rsock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &btrue, sizeof(btrue)); #endif #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT if (IS_IPV6(sas)) setsockopt(rsock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &btrue, sizeof(btrue)); #endif return recv_bytes; }
/* * hack_restrict - add/subtract/manipulate entries on the restrict list */ void hack_restrict( int op, sockaddr_u * resaddr, sockaddr_u * resmask, u_short mflags, u_short flags, u_long expire ) { int v6; restrict_u match; restrict_u * res; restrict_u ** plisthead; DPRINTF(1, ("restrict: op %d addr %s mask %s mflags %08x flags %08x\n", op, stoa(resaddr), stoa(resmask), mflags, flags)); if (NULL == resaddr) { REQUIRE(NULL == resmask); REQUIRE(RESTRICT_FLAGS == op); restrict_source_flags = flags; restrict_source_mflags = mflags; restrict_source_enabled = 1; return; } ZERO(match); #if 0 /* silence VC9 potentially uninit warnings */ // HMS: let's use a compiler-specific "enable" for this. res = NULL; v6 = 0; #endif if (IS_IPV4(resaddr)) { v6 = 0; /* * Get address and mask in host byte order for easy * comparison as u_int32 */ match.u.v4.addr = SRCADR(resaddr); match.u.v4.mask = SRCADR(resmask); match.u.v4.addr &= match.u.v4.mask; } else if (IS_IPV6(resaddr)) { v6 = 1; /* * Get address and mask in network byte order for easy * comparison as byte sequences (e.g. memcmp()) */ match.u.v6.mask = SOCK_ADDR6(resmask); MASK_IPV6_ADDR(&match.u.v6.addr, PSOCK_ADDR6(resaddr), &match.u.v6.mask); } else /* not IPv4 nor IPv6 */ REQUIRE(0); match.flags = flags; match.mflags = mflags; match.expire = expire; res = match_restrict_entry(&match, v6); switch (op) { case RESTRICT_FLAGS: /* * Here we add bits to the flags. If this is a * new restriction add it. */ if (NULL == res) { if (v6) { res = alloc_res6(); memcpy(res, &match, V6_SIZEOF_RESTRICT_U); plisthead = &restrictlist6; } else { res = alloc_res4(); memcpy(res, &match, V4_SIZEOF_RESTRICT_U); plisthead = &restrictlist4; } LINK_SORT_SLIST( *plisthead, res, (v6) ? res_sorts_before6(res, L_S_S_CUR()) : res_sorts_before4(res, L_S_S_CUR()), link, restrict_u); restrictcount++; if (RES_LIMITED & flags) inc_res_limited(); } else { if ((RES_LIMITED & flags) && !(RES_LIMITED & res->flags)) inc_res_limited(); res->flags |= flags; } break; case RESTRICT_UNFLAG: /* * Remove some bits from the flags. If we didn't * find this one, just return. */ if (res != NULL) { if ((RES_LIMITED & res->flags) && (RES_LIMITED & flags)) dec_res_limited(); res->flags &= ~flags; } break; case RESTRICT_REMOVE: case RESTRICT_REMOVEIF: /* * Remove an entry from the table entirely if we * found one. Don't remove the default entry and * don't remove an interface entry. */ if (res != NULL && (RESTRICT_REMOVEIF == op || !(RESM_INTERFACE & res->mflags)) && res != &restrict_def4 && res != &restrict_def6) free_res(res, v6); break; default: /* unknown op */ INSIST(0); break; } }
/* * restrictions - return restrictions for this host in *r4a */ void restrictions( sockaddr_u *srcadr, r4addr *r4a ) { restrict_u *match; struct in6_addr *pin6; REQUIRE(NULL != r4a); res_calls++; r4a->rflags = RES_IGNORE; r4a->ippeerlimit = 0; DPRINTF(1, ("restrictions: looking up %s\n", stoa(srcadr))); /* IPv4 source address */ if (IS_IPV4(srcadr)) { /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, * not later!) */ if (IN_CLASSD(SRCADR(srcadr))) { DPRINTF(1, ("restrictions: srcadr %s is multicast\n", stoa(srcadr))); r4a->ippeerlimit = 2; /* XXX: we should use a better value */ return; } match = match_restrict4_addr(SRCADR(srcadr), SRCPORT(srcadr)); INSIST(match != NULL); match->count++; /* * res_not_found counts only use of the final default * entry, not any "restrict default ntpport ...", which * would be just before the final default. */ if (&restrict_def4 == match) res_not_found++; else res_found++; r4a->rflags = match->rflags; r4a->ippeerlimit = match->ippeerlimit; } /* IPv6 source address */ if (IS_IPV6(srcadr)) { pin6 = PSOCK_ADDR6(srcadr); /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, * not later!) */ if (IN6_IS_ADDR_MULTICAST(pin6)) return; match = match_restrict6_addr(pin6, SRCPORT(srcadr)); INSIST(match != NULL); match->count++; if (&restrict_def6 == match) res_not_found++; else res_found++; r4a->rflags = match->rflags; r4a->ippeerlimit = match->ippeerlimit; } return; }
static int cmp_prefer_ipv4 (const void *addr1, const void *addr2) { return !IS_IPV4 (addr1) - !IS_IPV4 (addr2); }
void test_ip_address_create_and_destroy(void) { lagopus_result_t rc; const char *name1 = "127.0.0.1"; const char *name2 = "::1"; const char *name3 = "localhost"; //const char *name4 = "QkwUfh2GGN9sjCx"; const char *name5 = "127.0"; const char *name6 = "127.0.0.0"; const char *name7 = "127.0.0.1.1"; lagopus_ip_address_t *ip1 = NULL; lagopus_ip_address_t *ip2 = NULL; lagopus_ip_address_t *ip3 = NULL; //lagopus_ip_address_t *ip4 = NULL; lagopus_ip_address_t *ip5 = NULL; lagopus_ip_address_t *ip6 = NULL; bool is_ipv4 = false; { // Normal case(name = IPv4, ai_family = AF_INET) rc = lagopus_ip_address_create(name1, true, &ip1); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, rc); TEST_ASSERT_EQUAL(AF_INET, (ip1->saddr).ss_family); TEST_ASSERT_NOT_NULL_MESSAGE( ip1, "lagopus_ip_address_create() will create new ip_address"); TEST_ASSERT_EQUAL_STRING(name1, ip1->addr_str); TEST_ASSERT_EQUAL(AF_INET, IS_IPV4(ip1->is_ipv4)); rc = lagopus_ip_address_is_ipv4(ip1, &is_ipv4); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, rc); TEST_ASSERT_EQUAL(true, is_ipv4); lagopus_ip_address_destroy(ip1); // Normal case(name = IPv6, ai_family = AF_INET6) rc = lagopus_ip_address_create(name2, false, &ip2); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, rc); TEST_ASSERT_EQUAL(AF_INET6, (ip2->saddr).ss_family); TEST_ASSERT_NOT_NULL_MESSAGE( ip2, "lagopus_ip_address_create() will create new ip_address"); TEST_ASSERT_EQUAL_STRING(name2, ip2->addr_str); TEST_ASSERT_EQUAL(AF_INET6, IS_IPV4(ip2->is_ipv4)); rc = lagopus_ip_address_is_ipv4(ip2, &is_ipv4); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, rc); TEST_ASSERT_EQUAL(false, is_ipv4); lagopus_ip_address_destroy(ip2); // Normal case(name = IPv4, ai_family = AF_INET6) rc = lagopus_ip_address_create(name1, false, &ip1); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, rc); TEST_ASSERT_EQUAL(AF_INET, (ip1->saddr).ss_family); TEST_ASSERT_NOT_NULL_MESSAGE( ip1, "lagopus_ip_address_create() will create new ip_address"); TEST_ASSERT_EQUAL_STRING(name1, ip1->addr_str); TEST_ASSERT_EQUAL(AF_INET, IS_IPV4(ip1->is_ipv4)); // Normal case(name = IPv6, ai_family = AF_INET) rc = lagopus_ip_address_create(name2, true, &ip2); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, rc); TEST_ASSERT_EQUAL(AF_INET6, (ip2->saddr).ss_family); TEST_ASSERT_NOT_NULL_MESSAGE( ip2, "lagopus_ip_address_create() will create new ip_address"); TEST_ASSERT_EQUAL_STRING(name2, ip2->addr_str); TEST_ASSERT_EQUAL(AF_INET6, IS_IPV4(ip2->is_ipv4)); // Normal case(IP address obtained from a host name, // result addr_str = '127.0.0.1') rc = lagopus_ip_address_create(name3, true, &ip3); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, rc); TEST_ASSERT_EQUAL(AF_INET, (ip3->saddr).ss_family); TEST_ASSERT_NOT_NULL_MESSAGE( ip3, "lagopus_ip_address_create() will create new ip_address"); TEST_ASSERT_EQUAL_STRING(name1, ip3->addr_str); TEST_ASSERT_EQUAL(AF_INET, IS_IPV4(ip3->is_ipv4)); // Normal case(IP address obtained from a host name) //rc = lagopus_ip_address_create(name4, true, &ip4); //TEST_ASSERT_EQUAL(LAGOPUS_RESULT_ADDR_RESOLVER_FAILURE, rc); // Normal case(name = IPv4, ai_family = AF_INET, // name = '127.0', result addr_str = '127.0.0.0') rc = lagopus_ip_address_create(name5, true, &ip5); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, rc); TEST_ASSERT_EQUAL(AF_INET, (ip5->saddr).ss_family); TEST_ASSERT_NOT_NULL_MESSAGE( ip1, "lagopus_ip_address_create() will create new ip_address"); TEST_ASSERT_EQUAL_STRING(name6, ip5->addr_str); TEST_ASSERT_EQUAL(AF_INET, IS_IPV4(ip5->is_ipv4)); lagopus_ip_address_destroy(ip5); // Normal case(IP address bad format.) rc = lagopus_ip_address_create(name7, true, &ip6); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_ADDR_RESOLVER_FAILURE, rc); } // Abnormal case { rc = lagopus_ip_address_create(NULL, true, &ip1); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_INVALID_ARGS, rc); rc = lagopus_ip_address_create(name1, true, NULL); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_INVALID_ARGS, rc); } lagopus_ip_address_destroy(ip1); lagopus_ip_address_destroy(ip2); lagopus_ip_address_destroy(ip3); //lagopus_ip_address_destroy(ip4); }