int addr_btos(uint16_t bits, struct sockaddr *sa) { union sockunion *so = (union sockunion *)sa; #ifdef HAVE_SOCKADDR_IN6 if (bits > IP_ADDR_BITS && bits <= IP6_ADDR_BITS) { memset(&so->sin6, 0, sizeof(so->sin6)); #ifdef HAVE_SOCKADDR_SA_LEN so->sin6.sin6_len = IP6_ADDR_LEN + (bits / 8) + (bits % 8); #endif so->sin6.sin6_family = AF_INET6; return (addr_btom(bits, &so->sin6.sin6_addr, IP6_ADDR_LEN)); } else #endif if (bits <= IP_ADDR_BITS) { memset(&so->sin, 0, sizeof(so->sin)); #ifdef HAVE_SOCKADDR_SA_LEN so->sin.sin_len = IP_ADDR_LEN + (bits / 8) + (bits % 8); #endif so->sin.sin_family = AF_INET; return (addr_btom(bits, &so->sin.sin_addr, IP_ADDR_LEN)); } errno = EINVAL; return (-1); }
static void fr_to_fwc(const struct fw_rule *fr, struct ip_fwchange *fwc) { memset(fwc, 0, sizeof(*fwc)); strlcpy(fwc->fwc_rule.ipfw.fw_vianame, fr->fw_device, IFNAMSIZ); if (fr->fw_op == FW_OP_ALLOW) strlcpy(fwc->fwc_rule.label, IP_FW_LABEL_ACCEPT, sizeof(fwc->fwc_rule.label)); else strlcpy(fwc->fwc_rule.label, IP_FW_LABEL_BLOCK, sizeof(fwc->fwc_rule.label)); if (fr->fw_dir == FW_DIR_IN) strlcpy(fwc->fwc_label, IP_FW_LABEL_INPUT, sizeof(fwc->fwc_label)); else strlcpy(fwc->fwc_label, IP_FW_LABEL_OUTPUT, sizeof(fwc->fwc_label)); fwc->fwc_rule.ipfw.fw_proto = fr->fw_proto; fwc->fwc_rule.ipfw.fw_src.s_addr = fr->fw_src.addr_ip; fwc->fwc_rule.ipfw.fw_dst.s_addr = fr->fw_dst.addr_ip; addr_btom(fr->fw_src.addr_bits, &fwc->fwc_rule.ipfw.fw_smsk.s_addr, IP_ADDR_LEN); addr_btom(fr->fw_dst.addr_bits, &fwc->fwc_rule.ipfw.fw_dmsk.s_addr, IP_ADDR_LEN); /* XXX - ICMP? */ fwc->fwc_rule.ipfw.fw_spts[0] = fr->fw_sport[0]; fwc->fwc_rule.ipfw.fw_spts[1] = fr->fw_sport[1]; fwc->fwc_rule.ipfw.fw_dpts[0] = fr->fw_dport[0]; fwc->fwc_rule.ipfw.fw_dpts[1] = fr->fw_dport[1]; }
int route_get(route_t *route, struct route_entry *entry) { MIB_IPFORWARDROW ipfrow; DWORD mask; if (entry->route_dst.addr_type != ADDR_TYPE_IP || GetBestRoute(entry->route_dst.addr_ip, IP_ADDR_ANY, &ipfrow) != NO_ERROR) return (-1); if (ipfrow.dwForwardProto == 2 && /* XXX - MIB_IPPROTO_LOCAL */ (ipfrow.dwForwardNextHop|IP_CLASSA_NET) != (IP_ADDR_LOOPBACK|IP_CLASSA_NET) && !IP_LOCAL_GROUP(ipfrow.dwForwardNextHop)) { errno = ENXIO; SetLastError(ERROR_NO_DATA); return (-1); } addr_btom(entry->route_dst.addr_bits, &mask, IP_ADDR_LEN); entry->route_gw.addr_type = ADDR_TYPE_IP; entry->route_gw.addr_bits = IP_ADDR_BITS; entry->route_gw.addr_ip = ipfrow.dwForwardNextHop; return (0); }
int route_add(route_t *route, const struct route_entry *entry) { MIB_IPFORWARDROW ipfrow; struct addr net; memset(&ipfrow, 0, sizeof(ipfrow)); if (GetBestInterface(entry->route_gw.addr_ip, &ipfrow.dwForwardIfIndex) != NO_ERROR) return (-1); if (addr_net(&entry->route_dst, &net) < 0 || net.addr_type != ADDR_TYPE_IP) return (-1); ipfrow.dwForwardDest = net.addr_ip; addr_btom(entry->route_dst.addr_bits, &ipfrow.dwForwardMask, IP_ADDR_LEN); ipfrow.dwForwardNextHop = entry->route_gw.addr_ip; ipfrow.dwForwardType = 4; /* XXX - next hop != final dest */ ipfrow.dwForwardProto = 3; /* XXX - MIB_PROTO_NETMGMT */ if (CreateIpForwardEntry(&ipfrow) != NO_ERROR) return (-1); return (0); }
int intf_set(intf_t *intf, const struct intf_entry *entry) { /* * XXX - could set interface up/down via SetIfEntry(), * but what about the rest of the configuration? :-( * {Add,Delete}IPAddress for 2000/XP only */ #if 0 /* Set interface address. XXX - 2000/XP only? */ if (entry->intf_addr.addr_type == ADDR_TYPE_IP) { ULONG ctx = 0, inst = 0; UINT ip, mask; memcpy(&ip, &entry->intf_addr.addr_ip, IP_ADDR_LEN); addr_btom(entry->intf_addr.addr_bits, &mask, IP_ADDR_LEN); if (AddIPAddress(ip, mask, _find_ifindex(intf, entry->intf_name), &ctx, &inst) != NO_ERROR) { return (-1); } return (0); } #endif errno = ENOSYS; SetLastError(ERROR_NOT_SUPPORTED); return (-1); }
static void fr_to_pr(const struct fw_rule *fr, struct pf_rule *pr) { memset(pr, 0, sizeof(*pr)); strlcpy(pr->ifname, fr->fw_device, sizeof(pr->ifname)); pr->action = (fr->fw_op == FW_OP_ALLOW) ? PF_PASS : PF_DROP; pr->direction = (fr->fw_dir == FW_DIR_IN) ? PF_IN : PF_OUT; pr->proto = fr->fw_proto; pr->af = AF_INET; PFRA_ADDR(&pr->src) = fr->fw_src.addr_ip; addr_btom(fr->fw_src.addr_bits, &(PFRA_MASK(&pr->src)), IP_ADDR_LEN); PFRA_ADDR(&pr->dst) = fr->fw_dst.addr_ip; addr_btom(fr->fw_dst.addr_bits, &(PFRA_MASK(&pr->dst)), IP_ADDR_LEN); switch (fr->fw_proto) { case IP_PROTO_ICMP: if (fr->fw_sport[1]) pr->type = (u_char)(fr->fw_sport[0] & fr->fw_sport[1]) + 1; if (fr->fw_dport[1]) pr->code = (u_char)(fr->fw_dport[0] & fr->fw_dport[1]) + 1; break; case IP_PROTO_TCP: case IP_PROTO_UDP: pr->src.port[0] = htons(fr->fw_sport[0]); pr->src.port[1] = htons(fr->fw_sport[1]); if (pr->src.port[0] == pr->src.port[1]) { pr->src.port_op = PF_OP_EQ; } else pr->src.port_op = PF_OP_IRG; pr->dst.port[0] = htons(fr->fw_dport[0]); pr->dst.port[1] = htons(fr->fw_dport[1]); if (pr->dst.port[0] == pr->dst.port[1]) { pr->dst.port_op = PF_OP_EQ; } else pr->dst.port_op = PF_OP_IRG; break; } }
int addr_net(const struct addr *a, struct addr *b) { uint32_t mask; int i, j; if (a->addr_type == ADDR_TYPE_IP) { addr_btom(a->addr_bits, &mask, IP_ADDR_LEN); b->addr_type = ADDR_TYPE_IP; b->addr_bits = IP_ADDR_BITS; b->addr_ip = a->addr_ip & mask; } else if (a->addr_type == ADDR_TYPE_ETH) { memcpy(b, a, sizeof(*b)); if (a->addr_data8[0] & 0x1) memset(b->addr_data8 + 3, 0, 3); b->addr_bits = ETH_ADDR_BITS; } else if (a->addr_type == ADDR_TYPE_IP6) { b->addr_type = ADDR_TYPE_IP6; b->addr_bits = IP6_ADDR_BITS; memset(&b->addr_ip6, 0, IP6_ADDR_LEN); switch ((i = a->addr_bits / 32)) { case 4: b->addr_data32[3] = a->addr_data32[3]; case 3: b->addr_data32[2] = a->addr_data32[2]; case 2: b->addr_data32[1] = a->addr_data32[1]; case 1: b->addr_data32[0] = a->addr_data32[0]; } if ((j = a->addr_bits % 32) > 0) { addr_btom(j, &mask, sizeof(mask)); b->addr_data32[i] = a->addr_data32[i] & mask; } } else return (-1); return (0); }
int parse_host_range(const char *range, uint32_t *start, uint32_t *end) { struct addr addr, bcast; uint32_t val, mask; u_int u[4]; char *p, *s; int ret = -1; if ((p = strdup(range)) == NULL) return (ret); if (addr_aton(p, &addr) == 0 && addr.addr_type == ADDR_TYPE_IP) { if (addr.addr_bits != IP_ADDR_BITS) { *start = htonl(ntohl(addr.addr_ip) + 1); addr_bcast(&addr, &bcast); *end = htonl(ntohl(bcast.addr_ip) - 1); } else *start = *end = addr.addr_ip; ret = 0; } else if ((s = strchr(p, '-')) != NULL) { *s = '\0'; if (ip_aton(p, start) == 0) { if (ip_aton(s + 1, end) == 0) { ret = 0; } else if ((val = atoi(s + 1)) > 0 && val <= 0xff) { *end = (*start & IP_CLASSC_NET) | htonl(val); ret = 0; } } } else if ((s = strchr(p, '/')) != NULL) { *s = '\0'; memset(u, 0, sizeof(u)); if (sscanf(p, "%d.%d.%d.%d", &u[0], &u[1], &u[2], &u[3]) > 0 && addr_btom(atoi(s + 1), &mask, IP_ADDR_LEN) == 0) { val = ((u[0]<<24) | (u[1]<<16) | (u[2]<<8) | u[3]) & ntohl(mask); *start = htonl(val + 1); *end = htonl((val | ~(ntohl(mask))) - 1); ret = 0; } } free(p); return (ret); }
static int _arp_set_dev(const struct intf_entry *entry, void *arg) { struct arpreq *ar = (struct arpreq *)arg; struct addr dst; uint32_t mask; if (entry->intf_type == INTF_TYPE_ETH && entry->intf_addr.addr_type == ADDR_TYPE_IP) { addr_btom(entry->intf_addr.addr_bits, &mask, IP_ADDR_LEN); addr_ston((struct sockaddr *)&ar->arp_pa, &dst); if ((entry->intf_addr.addr_ip & mask) == (dst.addr_ip & mask)) { strlcpy(ar->arp_dev, entry->intf_name, sizeof(ar->arp_dev)); return (1); } } return (0); }
int addr_bcast(const struct addr *a, struct addr *b) { struct addr mask; if (a->addr_type == ADDR_TYPE_IP) { addr_btom(a->addr_bits, &mask.addr_ip, IP_ADDR_LEN); b->addr_type = ADDR_TYPE_IP; b->addr_bits = IP_ADDR_BITS; b->addr_ip = (a->addr_ip & mask.addr_ip) | (~0L & ~mask.addr_ip); } else if (a->addr_type == ADDR_TYPE_ETH) { b->addr_type = ADDR_TYPE_ETH; b->addr_bits = ETH_ADDR_BITS; memcpy(&b->addr_eth, ETH_ADDR_BROADCAST, ETH_ADDR_LEN); } else { /* XXX - no broadcast addresses in IPv6 */ errno = EINVAL; return (-1); } return (0); }
int route_delete(route_t *route, const struct route_entry *entry) { MIB_IPFORWARDROW ipfrow; DWORD mask; if (entry->route_dst.addr_type != ADDR_TYPE_IP || GetBestRoute(entry->route_dst.addr_ip, IP_ADDR_ANY, &ipfrow) != NO_ERROR) return (-1); addr_btom(entry->route_dst.addr_bits, &mask, IP_ADDR_LEN); if (ipfrow.dwForwardDest != entry->route_dst.addr_ip || ipfrow.dwForwardMask != mask) { errno = ENXIO; SetLastError(ERROR_NO_DATA); return (-1); } if (DeleteIpForwardEntry(&ipfrow) != NO_ERROR) return (-1); return (0); }