diff -Naur RELENG_2_3_2/sbin/dhclient/bpf.c RELENG_2_3_2+orange/sbin/dhclient/bpf.c --- RELENG_2_3_2/sbin/dhclient/bpf.c 2016-11-02 13:47:46.000000000 +0100 +++ RELENG_2_3_2+orange/sbin/dhclient/bpf.c 2017-02-01 08:35:48.615600187 +0100 @@ -96,24 +96,45 @@ * 'ip and udp and src port bootps and dst port (bootps or bootpc)' */ struct bpf_insn dhcp_bpf_wfilter[] = { - BPF_STMT(BPF_LD + BPF_B + BPF_IND, 14), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (IPVERSION << 4) + 5, 0, 12), - - /* Make sure this is an IP packet... */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 10), - + /* + * BROKEN/WIP: must also check (and pass) if packet has 802.1q encapsulation + */ + BPF_STMT(BPF_RET+BPF_K, (u_int)-1), + + /* Set indexing offset to 0 */ + BPF_STMT(BPF_LDX + BPF_B + BPF_IMM, 0), + + /* Load Ethernet type */ + BPF_STMT(BPF_LD + BPF_H + BPF_IND, 12), + + /* Check if it is an IP packet */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 2, 0), + + /* If not, check if it is a 802.1q packet */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_VLAN, 0, 10), + /* If it is, change offset for further tests */ + BPF_STMT(BPF_LDX + BPF_B + BPF_IMM, 4), + /* Make sure it's a UDP packet... */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23), + BPF_STMT(BPF_LD + BPF_B + BPF_IND, 23), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8), /* Make sure this isn't a fragment... */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), + BPF_STMT(BPF_LD + BPF_H + BPF_IND, 20), BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0), /* patched */ + /* + * IP checks + */ + /* Move index to accumulator */ + BPF_STMT(BPF_MISC + BPF_TXA, 0), /* Get the IP header length... */ BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14), - + /* Add it to the base offset */ + BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0), + /* Store it in X */ + BPF_STMT(BPF_MISC + BPF_TAX, 0), + /* Make sure it's from the right port... */ BPF_STMT(BPF_LD + BPF_H + BPF_IND, 14), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 68, 0, 3), @@ -154,12 +175,6 @@ p.bf_len = dhcp_bpf_wfilter_len; p.bf_insns = dhcp_bpf_wfilter; - if (dhcp_bpf_wfilter[7].k == 0x1fff) - dhcp_bpf_wfilter[7].k = htons(IP_MF|IP_OFFMASK); - - if (ioctl(info->wfdesc, BIOCSETWF, &p) < 0) - error("Can't install write filter program: %m"); - if (ioctl(info->wfdesc, BIOCLOCK, NULL) < 0) error("Cannot lock bpf"); @@ -175,6 +190,9 @@ if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1) error("setsockopt(IP_HDRINCL): %m"); + + note("Interface %s attached to bpf for sending", info->ifp->ifr_name); + info->ufdesc = sock; } @@ -274,6 +292,9 @@ error("Can't limit bpf descriptor: %m"); if (cap_ioctls_limit(info->rfdesc, cmds, 2) < 0 && errno != ENOSYS) error("Can't limit ioctls for bpf descriptor: %m"); + + note("Interface %s attached to bpf for receiving", info->ifp->ifr_name); + } void diff -Naur RELENG_2_3_2/sbin/dhclient/clparse.c RELENG_2_3_2+orange/sbin/dhclient/clparse.c --- RELENG_2_3_2/sbin/dhclient/clparse.c 2016-11-02 13:47:46.000000000 +0100 +++ RELENG_2_3_2+orange/sbin/dhclient/clparse.c 2017-02-01 07:54:48.741417401 +0100 @@ -75,6 +75,9 @@ memset(&top_level_config, 0, sizeof(top_level_config)); /* Set some defaults... */ + top_level_config.vlan_id = 0; + top_level_config.vlan_pcp = 0; + top_level_config.send_interface = NULL; top_level_config.timeout = 60; top_level_config.select_interval = 0; top_level_config.reboot_timeout = 10; @@ -186,6 +189,7 @@ * RETRY number | * REBOOT number | * SELECT_TIMEOUT number | + * PRIORITY number | * SCRIPT string | * interface-declaration | * LEASE client-lease-statement | @@ -198,6 +202,7 @@ int token; char *val; struct option *option; + time_t tmp; switch (next_token(&val, cfile)) { case SEND: @@ -257,6 +262,17 @@ case REBOOT: parse_lease_time(cfile, &config->reboot_timeout); return; + case VLAN_PCP: + parse_lease_time(cfile, &tmp); + config->vlan_pcp = (int)tmp; + return; + case VLAN_ID: + parse_lease_time(cfile, &tmp); + config->vlan_id = (int)tmp; + return; + case SEND_INTERFACE: + config->send_interface = parse_string(cfile); + return; case BACKOFF_CUTOFF: parse_lease_time(cfile, &config->backoff_cutoff); return; diff -Naur RELENG_2_3_2/sbin/dhclient/conflex.c RELENG_2_3_2+orange/sbin/dhclient/conflex.c --- RELENG_2_3_2/sbin/dhclient/conflex.c 2016-11-02 13:47:46.000000000 +0100 +++ RELENG_2_3_2+orange/sbin/dhclient/conflex.c 2017-02-01 07:57:35.515375976 +0100 @@ -467,10 +467,14 @@ return (REBOOT); if (!strcasecmp(atom + 1, "eject")) return (REJECT); + if (!strcasecmp(atom + 1, "fc3118-auth")) + return (REJECT); break; case 's': if (!strcasecmp(atom + 1, "earch")) return (SEARCH); + if (!strcasecmp(atom + 1, "end-interface")) + return (SEND_INTERFACE); if (!strcasecmp(atom + 1, "tarts")) return (STARTS); if (!strcasecmp(atom + 1, "iaddr")) @@ -519,6 +523,10 @@ case 'v': if (!strcasecmp(atom + 1, "endor-class")) return (VENDOR_CLASS); + if (!strcasecmp(atom + 1, "lan-id")) + return (VLAN_ID); + if (!strcasecmp(atom + 1, "lan-pcp")) + return (VLAN_PCP); break; case 'y': if (!strcasecmp(atom + 1, "iaddr")) diff -Naur RELENG_2_3_2/sbin/dhclient/dhcpd.h RELENG_2_3_2+orange/sbin/dhclient/dhcpd.h --- RELENG_2_3_2/sbin/dhclient/dhcpd.h 2016-11-02 13:47:46.000000000 +0100 +++ RELENG_2_3_2+orange/sbin/dhclient/dhcpd.h 2017-02-01 09:04:14.815293458 +0100 @@ -154,6 +154,9 @@ u_int8_t required_options[256]; u_int8_t requested_options[256]; int requested_option_count; + int vlan_id; + int vlan_pcp; + char *send_interface; time_t timeout; time_t initial_interval; time_t retry_interval; @@ -310,6 +313,7 @@ /* dispatch.c */ extern void (*bootp_packet_handler)(struct interface_info *, struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *); +void discover_interface(struct interface_info *); void discover_interfaces(struct interface_info *); void reinitialize_interfaces(void); void dispatch(void); diff -Naur RELENG_2_3_2/sbin/dhclient/dhcp.h RELENG_2_3_2+orange/sbin/dhclient/dhcp.h --- RELENG_2_3_2/sbin/dhclient/dhcp.h 2016-11-02 13:47:46.000000000 +0100 +++ RELENG_2_3_2+orange/sbin/dhclient/dhcp.h 2017-02-01 07:38:41.558192925 +0100 @@ -169,6 +169,7 @@ #define DHO_STREETTALK_SERVER 75 #define DHO_STREETTALK_DA_SERVER 76 #define DHO_DHCP_USER_CLASS_ID 77 +#define DHO_RFC3118_AUTH 90 #define DHO_DOMAIN_SEARCH 119 #define DHO_CLASSLESS_ROUTES 121 #define DHO_END 255 diff -Naur RELENG_2_3_2/sbin/dhclient/dhctoken.h RELENG_2_3_2+orange/sbin/dhclient/dhctoken.h --- RELENG_2_3_2/sbin/dhclient/dhctoken.h 2016-11-02 13:47:46.000000000 +0100 +++ RELENG_2_3_2+orange/sbin/dhclient/dhctoken.h 2017-02-01 08:06:21.143680056 +0100 @@ -129,6 +129,10 @@ #define AUTHORITATIVE 333 #define TOKEN_NOT 334 #define ALWAYS_REPLY_RFC1048 335 +#define VLAN_ID 336 +#define VLAN_PCP 337 +#define SEND_INTERFACE 338 +#define RFC3118_AUTH 339 #define is_identifier(x) ((x) >= FIRST_TOKEN && \ (x) != STRING && \ diff -Naur RELENG_2_3_2/sbin/dhclient/dispatch.c RELENG_2_3_2+orange/sbin/dhclient/dispatch.c --- RELENG_2_3_2/sbin/dhclient/dispatch.c 2016-11-02 13:47:46.000000000 +0100 +++ RELENG_2_3_2+orange/sbin/dhclient/dispatch.c 2017-02-01 08:15:57.968599688 +0100 @@ -67,12 +67,12 @@ * what subnet it's on, and add it to the list of interfaces. */ void -discover_interfaces(struct interface_info *iface) +discover_interface(struct interface_info *iface) { struct ifaddrs *ifap, *ifa; struct sockaddr_in foo; struct ifreq *tif; - + if (getifaddrs(&ifap) != 0) error("getifaddrs failed"); @@ -121,12 +121,42 @@ if (!iface->ifp) error("%s: not found", iface->name); + freeifaddrs(ifap); +} + +void +discover_interfaces(struct interface_info *iface) +{ + char *sname = iface->client->config->send_interface; + char *rname; - /* Register the interface... */ + strcpy(rname, iface->name); + + /* Discover the receiving interface... */ + note("Registering receive interface: %s", iface->name); + discover_interface(iface); if_register_receive(iface); - if_register_send(iface); add_protocol(iface->name, iface->rfdesc, got_one, iface); - freeifaddrs(ifap); + + /* Register the sending interface... */ + if (sname != NULL) { + note("Registering sending interface: %s", sname); + if (iface->client->config->vlan_id !=0) + note(" VLAN ID: %d, VLAN PCP: %d", + iface->client->config->vlan_id, iface->client->config->vlan_pcp); + + /* Change interface name for bpf registration */ + strlcpy(iface->ifp->ifr_name, sname, IFNAMSIZ); + + if_register_send(iface); + + /* Change name back to original */ + strlcpy(iface->ifp->ifr_name, rname, IFNAMSIZ); + } + else { + note("Registering same interface for sending"); + if_register_send(iface); + } } void diff -Naur RELENG_2_3_2/sbin/dhclient/packet.c RELENG_2_3_2+orange/sbin/dhclient/packet.c --- RELENG_2_3_2/sbin/dhclient/packet.c 2016-11-02 13:47:46.000000000 +0100 +++ RELENG_2_3_2+orange/sbin/dhclient/packet.c 2017-02-01 08:20:27.520994139 +0100 @@ -49,6 +49,7 @@ #include #include #include +#include #define ETHER_HEADER_SIZE (ETHER_ADDR_LEN * 2 + sizeof(u_int16_t)) @@ -93,18 +94,46 @@ int *bufix) { struct ether_header eh; + struct ether_vlan_header vh; - memset(eh.ether_dhost, 0xff, sizeof(eh.ether_dhost)); - if (interface->hw_address.hlen == sizeof(eh.ether_shost)) - memcpy(eh.ether_shost, interface->hw_address.haddr, - sizeof(eh.ether_shost)); - else - memset(eh.ether_shost, 0x00, sizeof(eh.ether_shost)); + int vlid = interface->client->config->vlan_id; + int vlpcp = interface->client->config->vlan_pcp; - eh.ether_type = htons(ETHERTYPE_IP); + /* If vlan id is not default, use a 802.1q VLAN frame */ + if (vlid != 0) { + memset(vh.evl_dhost, 0xff, sizeof(vh.evl_dhost)); + if (interface->hw_address.hlen == sizeof(eh.ether_shost)) + memcpy(vh.evl_shost, interface->hw_address.haddr, + sizeof(vh.evl_shost)); + else + memset(vh.evl_shost, 0x00, sizeof(vh.evl_shost)); + + /* Set encapsulation header type to 802.1q */ + vh.evl_encap_proto = htons(ETHERTYPE_VLAN); - memcpy(&buf[*bufix], &eh, ETHER_HEADER_SIZE); - *bufix += ETHER_HEADER_SIZE; + /* Add VLAN tag */ + vh.evl_tag = htons(EVL_MAKETAG(vlid, vlpcp, 0)); /* VLID, PRI, CFI */ + + /* Set IP ethernet type tag */ + vh.evl_proto = htons(ETHERTYPE_IP); + + memcpy(&buf[*bufix], &vh, sizeof(vh)); + *bufix += sizeof(vh); + } + else { + /* Standard IPv4 header */ + memset(eh.ether_dhost, 0xff, sizeof(eh.ether_dhost)); + if (interface->hw_address.hlen == sizeof(eh.ether_shost)) + memcpy(eh.ether_shost, interface->hw_address.haddr, + sizeof(eh.ether_shost)); + else + memset(eh.ether_shost, 0x00, sizeof(eh.ether_shost)); + + eh.ether_type = htons(ETHERTYPE_IP); + + memcpy(&buf[*bufix], &eh, ETHER_HEADER_SIZE); + *bufix += ETHER_HEADER_SIZE; + } } void diff -Naur RELENG_2_3_2/sbin/dhclient/tables.c RELENG_2_3_2+orange/sbin/dhclient/tables.c --- RELENG_2_3_2/sbin/dhclient/tables.c 2016-11-02 13:47:46.000000000 +0100 +++ RELENG_2_3_2+orange/sbin/dhclient/tables.c 2017-02-01 07:38:41.558192925 +0100 @@ -155,7 +155,7 @@ { "nds-context", "X", &dhcp_universe, 87 }, { "option-88", "X", &dhcp_universe, 88 }, { "option-89", "X", &dhcp_universe, 89 }, - { "option-90", "X", &dhcp_universe, 90 }, + { "rfc3118-auth", "X", &dhcp_universe, 90 }, { "option-91", "X", &dhcp_universe, 91 }, { "option-92", "X", &dhcp_universe, 92 }, { "option-93", "X", &dhcp_universe, 93 }, @@ -335,6 +335,8 @@ DHO_DHCP_REBINDING_TIME, DHO_DHCP_CLASS_IDENTIFIER, DHO_DHCP_CLIENT_IDENTIFIER, + DHO_DHCP_USER_CLASS_ID, + DHO_RFC3118_AUTH, DHO_SUBNET_MASK, DHO_TIME_OFFSET, DHO_CLASSLESS_ROUTES,