static int get_req_size(struct arglist *def) { char *gro = uml_vector_fetch_arg(def, "gro"); long result; if (gro != NULL) { if (kstrtoul(gro, 10, &result) == 0) { if (result > 0) return 65536; } } return get_mtu(def) + ETH_HEADER_OTHER + get_headroom(def) + SAFETY_MARGIN; }
static bool create_nic(char *nic, char *br, int pid, char **cnic) { char *veth1buf, *veth2buf; veth1buf = alloca(IFNAMSIZ); veth2buf = alloca(IFNAMSIZ); int ret, mtu; ret = snprintf(veth1buf, IFNAMSIZ, "%s", nic); if (ret < 0 || ret >= IFNAMSIZ) { fprintf(stderr, "host nic name too long\n"); return false; } /* create the nics */ if (instantiate_veth(veth1buf, &veth2buf) < 0) { fprintf(stderr, "Error creating veth tunnel\n"); return false; } if (strcmp(br, "none") != 0) { /* copy the bridge's mtu to both ends */ mtu = get_mtu(br); if (mtu != -1) { if (lxc_netdev_set_mtu(veth1buf, mtu) < 0 || lxc_netdev_set_mtu(veth2buf, mtu) < 0) { fprintf(stderr, "Failed setting mtu\n"); goto out_del; } } /* attach veth1 to bridge */ if (lxc_bridge_attach(lxcpath, lxcname, br, veth1buf) < 0) { fprintf(stderr, "Error attaching %s to %s\n", veth1buf, br); goto out_del; } } /* pass veth2 to target netns */ ret = lxc_netdev_move_by_name(veth2buf, pid, NULL); if (ret < 0) { fprintf(stderr, "Error moving %s to netns %d\n", veth2buf, pid); goto out_del; } *cnic = strdup(veth2buf); return true; out_del: lxc_netdev_delete_by_name(veth1buf); return false; }
/* * Check whether an interface is up and ready for service * * Arguments: * aip pointer to network interface block * * Returns: * 0 interface not ready, errno has reason * 1 interface is ready to go (interface block is updated) * */ int atmarp_if_ready(Atmarp_intf *aip) { int i, len, mtu, rc, sel; Atmarp *aap = NULL; struct atminfreq air; struct air_netif_rsp *netif_rsp = NULL; struct air_int_rsp *intf_rsp = NULL; struct sockaddr_in *ip_addr; struct sockaddr_in subnet_mask; Atm_addr_nsap *anp; /* * Get the IP address and physical interface name * associated with the network interface */ UM_ZERO(&air, sizeof(struct atminfreq)); air.air_opcode = AIOCS_INF_NIF; strcpy(air.air_netif_intf, aip->ai_intf); len = do_info_ioctl(&air, sizeof(struct air_netif_rsp)); if (len <= 0) { goto if_ready_fail; } netif_rsp = (struct air_netif_rsp *)air.air_buf_addr; ip_addr = (struct sockaddr_in *)&netif_rsp->anp_proto_addr; if (ip_addr->sin_family != AF_INET || ip_addr->sin_addr.s_addr == 0) { errno = EAFNOSUPPORT; goto if_ready_fail; } /* * Get the MTU for the network interface */ mtu = get_mtu(aip->ai_intf); if (mtu < 0) { goto if_ready_fail; } /* * Get the subnet mask associated with the * network interface */ rc = get_subnet_mask(aip->ai_intf, &subnet_mask); if (rc || subnet_mask.sin_family != AF_INET) { goto if_ready_fail; } /* * Get physical interface information */ UM_ZERO(&air, sizeof(struct atminfreq)); air.air_opcode = AIOCS_INF_INT; strcpy(air.air_int_intf, netif_rsp->anp_phy_intf); len = do_info_ioctl(&air, sizeof(struct air_int_rsp)); if (len <= 0) { goto if_ready_fail; } intf_rsp = (struct air_int_rsp *)air.air_buf_addr; /* * Check the signalling manager */ if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 && intf_rsp->anp_sig_proto != ATM_SIG_UNI31 && intf_rsp->anp_sig_proto != ATM_SIG_UNI40) { errno = EINVAL; goto if_ready_fail; } /* * Check the interface state */ if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) { errno = EINVAL; goto if_ready_fail; } /* * Check the address format */ if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR && !(intf_rsp->anp_addr.address_format == T_ATM_E164_ADDR && intf_rsp->anp_subaddr.address_format == T_ATM_ENDSYS_ADDR)) { errno = EINVAL; goto if_ready_fail; } /* * Find the selector byte value for the interface */ for (i=0; i<strlen(aip->ai_intf); i++) { if (aip->ai_intf[i] >= '0' && aip->ai_intf[i] <= '9') break; } sel = atoi(&aip->ai_intf[i]); /* * Make sure we're the server for this interface's LIS */ if (!atmarp_is_server(aip)) { rc = EINVAL; goto if_ready_fail; } /* * If we already have the interface active and the address * hasn't changed, return */ if (aip->ai_state != AI_STATE_NULL && bcmp((caddr_t) &((struct sockaddr_in *) &netif_rsp->anp_proto_addr)->sin_addr, (caddr_t)&aip->ai_ip_addr, sizeof(aip->ai_ip_addr)) == 0 && ATM_ADDR_EQUAL(&intf_rsp->anp_addr, &aip->ai_atm_addr) && ATM_ADDR_EQUAL(&intf_rsp->anp_subaddr, &aip->ai_atm_subaddr)) { return(1); } /* * Delete any existing ATMARP cache entry for this interface */ ATMARP_LOOKUP(aip, aip->ai_ip_addr.s_addr, aap); if (aap) { ATMARP_DELETE(aip, aap); UM_FREE(aap); } /* * Update the interface entry */ aip->ai_ip_addr = ((struct sockaddr_in *) &netif_rsp->anp_proto_addr)->sin_addr; aip->ai_subnet_mask = subnet_mask.sin_addr; aip->ai_mtu = mtu + 8; ATM_ADDR_COPY(&intf_rsp->anp_addr, &aip->ai_atm_addr); ATM_ADDR_COPY(&intf_rsp->anp_subaddr, &aip->ai_atm_subaddr); anp = (Atm_addr_nsap *)aip->ai_atm_addr.address; if (aip->ai_atm_addr.address_format == T_ATM_ENDSYS_ADDR) { anp->aan_sel = sel; } else if (aip->ai_atm_addr.address_format == T_ATM_E164_ADDR && aip->ai_atm_subaddr.address_format == T_ATM_ENDSYS_ADDR) { anp->aan_sel = sel; } /* * Get a new ATMARP cache for the interface */ aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp)); if (!aap) { atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)"); } UM_ZERO(aap, sizeof(Atmarp)); /* * Fill out the entry */ aap->aa_dstip = aip->ai_ip_addr; ATM_ADDR_COPY(&intf_rsp->anp_addr, &aap->aa_dstatm); ATM_ADDR_COPY(&intf_rsp->anp_subaddr, &aap->aa_dstatmsub); aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN; scsp_cache_key(&aap->aa_dstatm, &aap->aa_dstip, SCSP_ATMARP_KEY_LEN, aap->aa_key.key); aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN; aap->aa_seq = SCSP_CSA_SEQ_MIN; UM_COPY(&aap->aa_dstip.s_addr, aap->aa_oid.id, SCSP_ATMARP_ID_LEN); aap->aa_intf = aip; aap->aa_flags = AAF_SERVER; aap->aa_origin = UAO_LOCAL; /* * Add the entry to the cache */ ATMARP_ADD(aip, aap); /* * Free dynamic data */ UM_FREE(netif_rsp); UM_FREE(intf_rsp); return(1); if_ready_fail: if (netif_rsp) UM_FREE(netif_rsp); if (intf_rsp) UM_FREE(intf_rsp); return(0); }
int check_tun(const struct arguments *args, const struct epoll_event *ev, const int epoll_fd, int sessions, int maxsessions) { // Check tun error if (ev->events & EPOLLERR) { log_android(ANDROID_LOG_ERROR, "tun %d exception", args->tun); if (fcntl(args->tun, F_GETFL) < 0) { log_android(ANDROID_LOG_ERROR, "fcntl tun %d F_GETFL error %d: %s", args->tun, errno, strerror(errno)); report_exit(args, "fcntl tun %d F_GETFL error %d: %s", args->tun, errno, strerror(errno)); } else report_exit(args, "tun %d exception", args->tun); return -1; } // Check tun read if (ev->events & EPOLLIN) { uint8_t *buffer = malloc(get_mtu()); ssize_t length = read(args->tun, buffer, get_mtu()); if (length < 0) { free(buffer); log_android(ANDROID_LOG_ERROR, "tun %d read error %d: %s", args->tun, errno, strerror(errno)); if (errno == EINTR || errno == EAGAIN) // Retry later return 0; else { report_exit(args, "tun %d read error %d: %s", args->tun, errno, strerror(errno)); return -1; } } else if (length > 0) { // Write pcap record if (pcap_file != NULL) write_pcap_rec(buffer, (size_t) length); if (length > max_tun_msg) { max_tun_msg = length; log_android(ANDROID_LOG_WARN, "Maximum tun msg length %d", max_tun_msg); } // Handle IP from tun handle_ip(args, buffer, (size_t) length, epoll_fd, sessions, maxsessions); free(buffer); } else { // tun eof free(buffer); log_android(ANDROID_LOG_ERROR, "tun %d empty read", args->tun); report_exit(args, "tun %d empty read", args->tun); return -1; } } return 0; }
uint16_t get_default_mss(int version) { if (version == 4) return (uint16_t) (get_mtu() - sizeof(struct iphdr) - sizeof(struct tcphdr)); else return (uint16_t) (get_mtu() - sizeof(struct ip6_hdr) - sizeof(struct tcphdr)); }
static int create_nic(char *nic, char *br, int pid, char **cnic) { char veth1buf[IFNAMSIZ], veth2buf[IFNAMSIZ]; int mtu, ret; ret = snprintf(veth1buf, IFNAMSIZ, "%s", nic); if (ret < 0 || ret >= IFNAMSIZ) { usernic_error("%s", "Could not create nic name\n"); return -1; } ret = snprintf(veth2buf, IFNAMSIZ, "%sp", veth1buf); if (ret < 0 || ret >= IFNAMSIZ) { usernic_error("%s\n", "Could not create nic name"); return -1; } /* create the nics */ ret = instantiate_veth(veth1buf, veth2buf); if (ret < 0) { usernic_error("%s", "Error creating veth tunnel\n"); return -1; } if (strcmp(br, "none")) { /* copy the bridge's mtu to both ends */ mtu = get_mtu(br); if (mtu > 0) { ret = lxc_netdev_set_mtu(veth1buf, mtu); if (ret < 0) { usernic_error("Failed to set mtu to %d on %s\n", mtu, veth1buf); goto out_del; } ret = lxc_netdev_set_mtu(veth2buf, mtu); if (ret < 0) { usernic_error("Failed to set mtu to %d on %s\n", mtu, veth2buf); goto out_del; } } /* attach veth1 to bridge */ ret = lxc_bridge_attach(br, veth1buf); if (ret < 0) { usernic_error("Error attaching %s to %s\n", veth1buf, br); goto out_del; } } /* pass veth2 to target netns */ ret = lxc_netdev_move_by_name(veth2buf, pid, NULL); if (ret < 0) { usernic_error("Error moving %s to network namespace of %d\n", veth2buf, pid); goto out_del; } *cnic = strdup(veth2buf); if (!*cnic) { usernic_error("Failed to copy string \"%s\"\n", veth2buf); return -1; } return 0; out_del: lxc_netdev_delete_by_name(veth1buf); return -1; }
size_t send_message (const interface_t *iface, const dhcp_t *dhcp, unsigned long xid, char type, const options_t *options) { dhcpmessage_t message; struct udp_dhcp_packet packet; unsigned char *m = (unsigned char *) &message; unsigned char *p = (unsigned char *) &message.options; unsigned char *n_params = NULL; unsigned long l; struct in_addr from; struct in_addr to; long up = uptime() - iface->start_uptime; uint32_t ul; uint16_t sz; unsigned int message_length; if (!iface || !options || !dhcp) return -1; memset (&from, 0, sizeof (from)); memset (&to, 0, sizeof (to)); if (type == DHCP_RELEASE) to.s_addr = dhcp->serveraddress.s_addr; memset (&message, 0, sizeof (dhcpmessage_t)); if (type == DHCP_INFORM || type == DHCP_RELEASE || type == DHCP_REQUEST) { message.ciaddr = iface->previous_address.s_addr; from.s_addr = iface->previous_address.s_addr; } message.op = DHCP_BOOTREQUEST; message.hwtype = iface->family; switch (iface->family) { case ARPHRD_ETHER: case ARPHRD_IEEE802: message.hwlen = ETHER_ADDR_LEN; memcpy (&message.chaddr, &iface->hwaddr, ETHER_ADDR_LEN); break; case ARPHRD_IEEE1394: case ARPHRD_INFINIBAND: if (message.ciaddr == 0) message.flags = htons (BROADCAST_FLAG); message.hwlen = 0; break; default: logger (LOG_ERR, "dhcp: unknown hardware type %d", iface->family); } if (up < 0 || up > UINT16_MAX) message.secs = htons ((short) UINT16_MAX); else message.secs = htons (up); message.xid = xid; message.cookie = htonl (MAGIC_COOKIE); *p++ = DHCP_MESSAGETYPE; *p++ = 1; *p++ = type; if (type == DHCP_REQUEST) { *p++ = DHCP_MAXMESSAGESIZE; *p++ = 2; sz = get_mtu (iface->name); if (sz < MTU_MIN) { if (set_mtu (iface->name, MTU_MIN) == 0) sz = MTU_MIN; } sz = htons (sz); memcpy (p, &sz, 2); p += 2; } #define PUTADDR(_type, _val) \ { \ *p++ = _type; \ *p++ = 4; \ memcpy (p, &_val.s_addr, 4); \ p += 4; \ } if (dhcp->address.s_addr != 0 && iface->previous_address.s_addr == 0 && type != DHCP_RELEASE) PUTADDR (DHCP_ADDRESS, dhcp->address); if (dhcp->serveraddress.s_addr != 0 && dhcp->address.s_addr !=0 && (iface->previous_address.s_addr == 0 || type == DHCP_RELEASE)) PUTADDR (DHCP_SERVERIDENTIFIER, dhcp->serveraddress); #undef PUTADDR if (type == DHCP_REQUEST || type == DHCP_DISCOVER) { if (options->leasetime != 0) { *p++ = DHCP_LEASETIME; *p++ = 4; ul = htonl (options->leasetime); memcpy (p, &ul, 4); p += 4; } } if (type == DHCP_DISCOVER || type == DHCP_INFORM || type == DHCP_REQUEST) { *p++ = DHCP_PARAMETERREQUESTLIST; n_params = p; *p++ = 0; /* Only request DNSSERVER in discover to keep the packets small. RFC2131 Section 3.5 states that the REQUEST must include the list from the DISCOVER message, so I think we can safely do this. */ if (type == DHCP_DISCOVER) *p++ = DHCP_DNSSERVER; else { *p++ = DHCP_RENEWALTIME; *p++ = DHCP_REBINDTIME; *p++ = DHCP_NETMASK; *p++ = DHCP_BROADCAST; *p++ = DHCP_CSR; /* RFC 3442 states classless static routes should be before routers * and static routes as classless static routes override them both */ *p++ = DHCP_STATICROUTE; *p++ = DHCP_ROUTERS; *p++ = DHCP_HOSTNAME; *p++ = DHCP_DNSSEARCH; *p++ = DHCP_DNSDOMAIN; *p++ = DHCP_DNSSERVER; *p++ = DHCP_NISDOMAIN; *p++ = DHCP_NISSERVER; *p++ = DHCP_NTPSERVER; *p++ = DHCP_MTU; *p++ = DHCP_ROOTPATH; /* These parameters were requested by dhcpcd-2.0 and earlier but we never did anything with them */ /* *p++ = DHCP_DEFAULTIPTTL; *p++ = DHCP_MASKDISCOVERY; *p++ = DHCP_ROUTERDISCOVERY; */ } *n_params = p - n_params - 1; if (*options->hostname) { if (options->fqdn == FQDN_DISABLE) { *p++ = DHCP_HOSTNAME; *p++ = l = strlen (options->hostname); memcpy (p, options->hostname, l); p += l; } else { /* Draft IETF DHC-FQDN option (81) */ *p++ = DHCP_FQDN; *p++ = (l = strlen (options->hostname)) + 3; /* Flags: 0000NEOS * S: 1 => Client requests Server to update A RR in DNS as well as PTR * O: 1 => Server indicates to client that DNS has been updated * E: 1 => Name data is DNS format * N: 1 => Client requests Server to not update DNS */ *p++ = options->fqdn & 0x9; *p++ = 0; /* rcode1, response from DNS server for PTR RR */ *p++ = 0; /* rcode2, response from DNS server for A RR if S=1 */ memcpy (p, options->hostname, l); p += l; } } } if (type != DHCP_DECLINE && type != DHCP_RELEASE) { if (options->userclass_len > 0) { *p++ = DHCP_USERCLASS; *p++ = options->userclass_len; memcpy (p, &options->userclass, options->userclass_len); p += options->userclass_len; } *p++ = DHCP_CLASSID; *p++ = l = strlen (options->classid); memcpy (p, options->classid, l); p += l; } *p++ = DHCP_CLIENTID; if (options->clientid[0]) { l = strlen (options->clientid); *p++ = l + 1; *p++ = 0; /* string */ memcpy (p, options->clientid, l); p += l; } else { *p++ = iface->hwlen + 1; *p++ = iface->family; memcpy (p, iface->hwaddr, iface->hwlen); p += iface->hwlen; } #ifdef BOOTP_MESSAGE_LENTH_MIN /* Some crappy DHCP servers think they have to obey the BOOTP minimum * messag length. They are wrong, but we should still cater for them */ while (p - m < BOOTP_MESSAGE_LENTH_MIN - 1) *p++ = DHCP_PAD; #endif *p++ = DHCP_END; message_length = p - m; memset (&packet, 0, sizeof (struct udp_dhcp_packet)); make_dhcp_packet (&packet, (unsigned char *) &message, message_length, from, to); logger (LOG_DEBUG, "sending %s with xid 0x%lx", dhcp_message[(int) type], xid); return send_packet (iface, ETHERTYPE_IP, (unsigned char *) &packet, message_length + sizeof (struct ip) + sizeof (struct udphdr)); }
ssize_t make_message(struct dhcp_message **message, const struct interface *iface, const struct dhcp_lease *lease, uint32_t xid, uint8_t type, const struct options *options) { struct dhcp_message *dhcp; uint8_t *m, *lp, *p; uint8_t *n_params = NULL; time_t up = uptime() - iface->start_uptime; uint32_t ul; uint16_t sz; const struct dhcp_opt *opt; size_t len; const char *hp; dhcp = xzalloc(sizeof (*dhcp)); m = (uint8_t *)dhcp; p = dhcp->options; if ((type == DHCP_INFORM || type == DHCP_RELEASE || type == DHCP_REQUEST) && !IN_LINKLOCAL(ntohl(iface->addr.s_addr))) { dhcp->ciaddr = iface->addr.s_addr; /* Just incase we haven't actually configured the address yet */ if (type == DHCP_INFORM && iface->addr.s_addr == 0) dhcp->ciaddr = lease->addr.s_addr; /* Zero the address if we're currently on a different subnet */ if (type == DHCP_REQUEST && iface->net.s_addr != lease->net.s_addr) dhcp->ciaddr = 0; } dhcp->op = DHCP_BOOTREQUEST; dhcp->hwtype = iface->family; switch (iface->family) { case ARPHRD_ETHER: case ARPHRD_IEEE802: dhcp->hwlen = ETHER_ADDR_LEN; memcpy(&dhcp->chaddr, &iface->hwaddr, ETHER_ADDR_LEN); break; case ARPHRD_IEEE1394: case ARPHRD_INFINIBAND: dhcp->hwlen = 0; if (dhcp->ciaddr == 0 && type != DHCP_DECLINE && type != DHCP_RELEASE) dhcp->flags = htons(BROADCAST_FLAG); break; } if (type != DHCP_DECLINE && type != DHCP_RELEASE) { if (up < 0 || up > (time_t)UINT16_MAX) dhcp->secs = htons((uint16_t)UINT16_MAX); else dhcp->secs = htons(up); } dhcp->xid = xid; dhcp->cookie = htonl(MAGIC_COOKIE); *p++ = DHO_MESSAGETYPE; *p++ = 1; *p++ = type; if (iface->clientid) { *p++ = DHO_CLIENTID; memcpy(p, iface->clientid, iface->clientid[0] + 1); p += iface->clientid[0] + 1; } if (lease->addr.s_addr && !IN_LINKLOCAL(htonl(lease->addr.s_addr))) { if (type == DHCP_DECLINE || type == DHCP_DISCOVER || (type == DHCP_REQUEST && lease->addr.s_addr != iface->addr.s_addr)) { PUTADDR(DHO_IPADDRESS, lease->addr); if (lease->server.s_addr) PUTADDR(DHO_SERVERID, lease->server); } } if (type == DHCP_DECLINE) { *p++ = DHO_MESSAGE; len = strlen(DAD); *p++ = len; memcpy(p, DAD, len); p += len; } if (type == DHCP_RELEASE) { if (lease->server.s_addr) PUTADDR(DHO_SERVERID, lease->server); } if (type == DHCP_DISCOVER || type == DHCP_INFORM || type == DHCP_REQUEST) { *p++ = DHO_MAXMESSAGESIZE; *p++ = 2; sz = get_mtu(iface->name); if (sz < MTU_MIN) { if (set_mtu(iface->name, MTU_MIN) == 0) sz = MTU_MIN; } sz = htons(sz); memcpy(p, &sz, 2); p += 2; if (options->userclass[0]) { *p++ = DHO_USERCLASS; memcpy(p, options->userclass, options->userclass[0] + 1); p += options->userclass[0] + 1; } if (options->vendorclassid[0]) { *p++ = DHO_VENDORCLASSID; memcpy(p, options->vendorclassid, options->vendorclassid[0] + 1); p += options->vendorclassid[0] + 1; } if (type != DHCP_INFORM) { if (options->leasetime != 0) { *p++ = DHO_LEASETIME; *p++ = 4; ul = htonl(options->leasetime); memcpy(p, &ul, 4); p += 4; } } /* Regardless of RFC2132, we should always send a hostname * upto the first dot (the short hostname) as otherwise * confuses some DHCP servers when updating DNS. * The FQDN option should be used if a FQDN is required. */ if (options->hostname[0]) { *p++ = DHO_HOSTNAME; hp = strchr(options->hostname, '.'); if (hp) len = hp - options->hostname; else len = strlen(options->hostname); *p++ = len; memcpy(p, options->hostname, len); p += len; } if (options->fqdn != FQDN_DISABLE) { /* IETF DHC-FQDN option (81), RFC4702 */ *p++ = DHO_FQDN; lp = p; *p++ = 3; /* * Flags: 0000NEOS * S: 1 => Client requests Server to update * a RR in DNS as well as PTR * O: 1 => Server indicates to client that * DNS has been updated * E: 1 => Name data is DNS format * N: 1 => Client requests Server to not * update DNS */ *p++ = (options->fqdn & 0x09) | 0x04; *p++ = 0; /* from server for PTR RR */ *p++ = 0; /* from server for A RR if S=1 */ ul = encode_rfc1035(options->hostname, p); *lp += ul; p += ul; } /* vendor is already encoded correctly, so just add it */ if (options->vendor[0]) { *p++ = DHO_VENDOR; memcpy(p, options->vendor, options->vendor[0] + 1); p += options->vendor[0] + 1; } *p++ = DHO_PARAMETERREQUESTLIST; n_params = p; *p++ = 0; for (opt = dhcp_opts; opt->option; opt++) { if (!(opt->type & REQUEST || has_option_mask(options->requestmask, opt->option))) continue; switch (opt->option) { case DHO_RENEWALTIME: /* FALLTHROUGH */ case DHO_REBINDTIME: if (type == DHCP_INFORM) continue; break; } *p++ = opt->option; } *n_params = p - n_params - 1; } *p++ = DHO_END; #ifdef BOOTP_MESSAGE_LENTH_MIN /* Some crappy DHCP servers think they have to obey the BOOTP minimum * message length. * They are wrong, but we should still cater for them. */ while (p - m < BOOTP_MESSAGE_LENTH_MIN) *p++ = DHO_PAD; #endif *message = dhcp; return p - m; }
size_t send_message (const interface_t *iface, const dhcp_t *dhcp, unsigned long xid, char type, const options_t *options) { struct udp_dhcp_packet *packet; dhcpmessage_t *message; unsigned char *m; unsigned char *p; unsigned char *n_params = NULL; unsigned long l; struct in_addr from; struct in_addr to; time_t up = uptime() - iface->start_uptime; uint32_t ul; uint16_t sz; unsigned int message_length; size_t retval; if (!iface || !options || !dhcp) return -1; memset (&from, 0, sizeof (from)); memset (&to, 0, sizeof (to)); if (type == DHCP_RELEASE) to.s_addr = dhcp->serveraddress.s_addr; message = xmalloc (sizeof (dhcpmessage_t)); memset (message, 0, sizeof (dhcpmessage_t)); m = (unsigned char *) message; p = (unsigned char *) &message->options; if ((type == DHCP_INFORM || type == DHCP_RELEASE || type == DHCP_REQUEST) && ! IN_LINKLOCAL (iface->previous_address.s_addr)) { message->ciaddr = iface->previous_address.s_addr; from.s_addr = iface->previous_address.s_addr; /* Just incase we haven't actually configured the address yet */ if (type == DHCP_INFORM && iface->previous_address.s_addr == 0) message->ciaddr = dhcp->address.s_addr; /* Zero the address if we're currently on a different subnet */ if (type == DHCP_REQUEST && iface->previous_netmask.s_addr != dhcp->netmask.s_addr) message->ciaddr = from.s_addr = 0; } message->op = DHCP_BOOTREQUEST; message->hwtype = iface->family; switch (iface->family) { case ARPHRD_ETHER: case ARPHRD_IEEE802: message->hwlen = ETHER_ADDR_LEN; memcpy (&message->chaddr, &iface->hwaddr, ETHER_ADDR_LEN); break; case ARPHRD_IEEE1394: case ARPHRD_INFINIBAND: if (message->ciaddr == 0) message->flags = (int16_t) htons (BROADCAST_FLAG); message->hwlen = 0; break; default: logger (LOG_ERR, "dhcp: unknown hardware type %d", iface->family); } if (up < 0 || up > UINT16_MAX) message->secs = htons ((short) UINT16_MAX); else message->secs = htons (up); message->xid = xid; message->cookie = htonl (MAGIC_COOKIE); *p++ = DHCP_MESSAGETYPE; *p++ = 1; *p++ = type; if (type == DHCP_REQUEST) { *p++ = DHCP_MAXMESSAGESIZE; *p++ = 2; sz = get_mtu (iface->name); if (sz < MTU_MIN) { if (set_mtu (iface->name, MTU_MIN) == 0) sz = MTU_MIN; } sz = htons (sz); memcpy (p, &sz, 2); p += 2; } if (type != DHCP_INFORM) { #define PUTADDR(_type, _val) \ { \ *p++ = _type; \ *p++ = 4; \ memcpy (p, &_val.s_addr, 4); \ p += 4; \ } if (IN_LINKLOCAL (dhcp->address.s_addr)) logger (LOG_ERR, "cannot request a link local address"); else { if (dhcp->address.s_addr != iface->previous_address.s_addr && type != DHCP_RELEASE) PUTADDR (DHCP_ADDRESS, dhcp->address); if (dhcp->serveraddress.s_addr != 0 && dhcp->address.s_addr !=0 && (iface->previous_address.s_addr == 0 || type == DHCP_RELEASE)) PUTADDR (DHCP_SERVERIDENTIFIER, dhcp->serveraddress); } #undef PUTADDR } if (type == DHCP_REQUEST || type == DHCP_DISCOVER) { if (options->leasetime != 0) { *p++ = DHCP_LEASETIME; *p++ = 4; ul = htonl (options->leasetime); memcpy (p, &ul, 4); p += 4; } } if (type == DHCP_DISCOVER || type == DHCP_INFORM || type == DHCP_REQUEST) { *p++ = DHCP_PARAMETERREQUESTLIST; n_params = p; *p++ = 0; /* Only request DNSSERVER in discover to keep the packets small. RFC2131 Section 3.5 states that the REQUEST must include the list from the DISCOVER message, so I think we can safely do this. */ if (type == DHCP_DISCOVER && ! options->test) *p++ = DHCP_DNSSERVER; else { if (type != DHCP_INFORM) { *p++ = DHCP_RENEWALTIME; *p++ = DHCP_REBINDTIME; } *p++ = DHCP_NETMASK; *p++ = DHCP_BROADCAST; *p++ = DHCP_CSR; /* RFC 3442 states classless static routes should be before routers * and static routes as classless static routes override them both */ *p++ = DHCP_STATICROUTE; *p++ = DHCP_ROUTERS; *p++ = DHCP_HOSTNAME; *p++ = DHCP_DNSSEARCH; *p++ = DHCP_DNSDOMAIN; *p++ = DHCP_DNSSERVER; *p++ = DHCP_NISDOMAIN; *p++ = DHCP_NISSERVER; *p++ = DHCP_NTPSERVER; *p++ = DHCP_MTU; *p++ = DHCP_ROOTPATH; *p++ = DHCP_SIPSERVER; } *n_params = p - n_params - 1; if (options->hostname[0]) { if (options->fqdn == FQDN_DISABLE) { *p++ = DHCP_HOSTNAME; *p++ = l = strlen (options->hostname); memcpy (p, options->hostname, l); p += l; } else { /* Draft IETF DHC-FQDN option (81) */ *p++ = DHCP_FQDN; *p++ = (l = strlen (options->hostname)) + 3; /* Flags: 0000NEOS * S: 1 => Client requests Server to update A RR in DNS as well as PTR * O: 1 => Server indicates to client that DNS has been updated * E: 1 => Name data is DNS format * N: 1 => Client requests Server to not update DNS */ *p++ = options->fqdn & 0x9; *p++ = 0; /* rcode1, response from DNS server for PTR RR */ *p++ = 0; /* rcode2, response from DNS server for A RR if S=1 */ memcpy (p, options->hostname, l); p += l; } } } if (type != DHCP_DECLINE && type != DHCP_RELEASE) { if (options->userclass_len > 0) { *p++ = DHCP_USERCLASS; *p++ = options->userclass_len; memcpy (p, &options->userclass, options->userclass_len); p += options->userclass_len; } if (options->classid_len > 0) { *p++ = DHCP_CLASSID; *p++ = options->classid_len; memcpy (p, options->classid, options->classid_len); p += options->classid_len; } } *p++ = DHCP_CLIENTID; if (options->clientid_len > 0) { *p++ = options->clientid_len + 1; *p++ = 0; /* string */ memcpy (p, options->clientid, options->clientid_len); p += options->clientid_len; #ifdef ENABLE_DUID } else if (iface->duid && options->clientid_len != -1) { *p++ = iface->duid_length + 5; *p++ = 255; /* RFC 4361 */ /* IAID is 4 bytes, so if the interface name is 4 bytes then use it */ if (strlen (iface->name) == 4) { memcpy (p, iface->name, 4); } else { /* Name isn't 4 bytes, so use the index */ ul = htonl (if_nametoindex (iface->name)); memcpy (p, &ul, 4); } p += 4; memcpy (p, iface->duid, iface->duid_length); p += iface->duid_length; #endif } else { *p++ = iface->hwlen + 1; *p++ = iface->family; memcpy (p, iface->hwaddr, iface->hwlen); p += iface->hwlen; } *p++ = DHCP_END; #ifdef BOOTP_MESSAGE_LENTH_MIN /* Some crappy DHCP servers think they have to obey the BOOTP minimum * messag length. They are wrong, but we should still cater for them */ while (p - m < BOOTP_MESSAGE_LENTH_MIN) *p++ = DHCP_PAD; #endif message_length = p - m; packet = xmalloc (sizeof (struct udp_dhcp_packet)); memset (packet, 0, sizeof (struct udp_dhcp_packet)); make_dhcp_packet (packet, (unsigned char *) message, message_length, from, to); free (message); logger (LOG_DEBUG, "sending %s with xid 0x%lx", dhcp_message[(int) type], xid); retval = send_packet (iface, ETHERTYPE_IP, (unsigned char *) packet, message_length + sizeof (struct ip) + sizeof (struct udphdr)); free (packet); return (retval); }
void ring_bond_ib::create_slave_list(in_addr_t local_if, ring_resource_creation_info_t* p_ring_info, bool active_slaves[], uint16_t pkey) { for (uint32_t i = 0; i < m_n_num_resources; i++) { m_bond_rings[i] = new ring_ib(local_if, &p_ring_info[i], 1, active_slaves[i], pkey, get_mtu(), this); // get_mtu() reads the MTU from ifconfig when created. Now passing it to its slaves. could have sent 0 here, as the MTU of the bond is already on the bond if (m_min_devices_tx_inline < 0) m_min_devices_tx_inline = m_bond_rings[i]->get_max_tx_inline(); else m_min_devices_tx_inline = min(m_min_devices_tx_inline, m_bond_rings[i]->get_max_tx_inline()); if (active_slaves[i]) { m_active_rings[i] = m_bond_rings[i]; } else { m_active_rings[i] = NULL; } } close_gaps_active_rings(); }
static int get_interfaces(struct if_stats *ifs) { char buf[PAGE_SIZE]; char *p; int ret, nr, fd; fd = open(PROC_NET_DEV, O_RDONLY); if (fd < 0) { perror("open"); exit(EXIT_FAILURE); } ret = read(fd, buf, sizeof(buf) - 1); if (ret < 0) { perror("read"); exit(EXIT_FAILURE); } else if (!ret) { fprintf(stderr, "reading " PROC_NET_DEV " returned premature EOF\n"); exit(EXIT_FAILURE); } buf[ret] = '\0'; /* skip down to the third line */ p = strchr(buf, '\n'); if (!p) { fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n"); exit(EXIT_FAILURE); } p = strchr(p + 1, '\n'); if (!p) { fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n"); exit(EXIT_FAILURE); } p += 1; /* * Key: * if: (Rx) bytes packets errs drop fifo frame compressed multicast \ * (Tx) bytes packets errs drop fifo colls carrier compressed */ for (nr = 0; nr < MAX_IF; nr++) { char *c; ret = sscanf(p, "%" STR(IFNAMSIZ) "s", ifs->name); if (ret != 1) { fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n"); exit(EXIT_FAILURE); } /* * This works around a bug in the proc file where large interface names * or Rx byte counts eat the delimiter, breaking sscanf. */ c = strchr(ifs->name, ':'); if (c) *c = '\0'; p = strchr(p, ':') + 1; ret = sscanf(p, "%u %u %u %u %*u %*u %*u %*u %u %u %u %u %*u %*u " "%*u %*u\n", &ifs->rx_bytes, &ifs->rx_packets, &ifs->rx_errors, &ifs->rx_dropped, &ifs->tx_bytes, &ifs->tx_packets, &ifs->tx_errors, &ifs->tx_dropped); if (ret != 8) { fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n"); exit(EXIT_FAILURE); } ifs->mtu = get_mtu(ifs->name); p = strchr(p, '\n') + 1; if (*p == '\0') { nr++; break; } ifs++; } ret = close(fd); if (ret) { perror("close"); exit(EXIT_FAILURE); } return nr; }
void ring_bond_eth::create_slave_list(in_addr_t local_if, ring_resource_creation_info_t* p_ring_info, bool active_slaves[], uint16_t vlan) { for (uint32_t i = 0; i < m_n_num_resources; i++) { m_bond_rings[i] = new ring_eth(local_if, &p_ring_info[i], 1, active_slaves[i], vlan, get_mtu(), this); if (m_min_devices_tx_inline < 0) m_min_devices_tx_inline = m_bond_rings[i]->get_max_tx_inline(); else m_min_devices_tx_inline = min(m_min_devices_tx_inline, m_bond_rings[i]->get_max_tx_inline()); if (active_slaves[i]) { m_active_rings[i] = m_bond_rings[i]; } else { m_active_rings[i] = NULL; } } close_gaps_active_rings(); }
struct if_head * discover_interfaces(struct dhcpcd_ctx *ctx, int argc, char * const *argv) { struct ifaddrs *ifaddrs, *ifa; char *p; int i, sdl_type; struct if_head *ifs; struct interface *ifp; #ifdef __linux__ char ifn[IF_NAMESIZE]; #endif #ifdef INET const struct sockaddr_in *addr; const struct sockaddr_in *net; const struct sockaddr_in *dst; #endif #ifdef INET6 const struct sockaddr_in6 *sin6; int ifa_flags; #endif #ifdef AF_LINK const struct sockaddr_dl *sdl; #ifdef SIOCGIFPRIORITY struct ifreq ifr; int s_inet; #endif #ifdef IFLR_ACTIVE struct if_laddrreq iflr; int s_link; #endif #ifdef SIOCGIFPRIORITY if ((s_inet = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return NULL; #endif #ifdef IFLR_ACTIVE if ((s_link = socket(AF_LINK, SOCK_DGRAM, 0)) == -1) { #ifdef SIOCGIFPRIORITY close(s_inet); #endif return NULL; } memset(&iflr, 0, sizeof(iflr)); #endif #elif AF_PACKET const struct sockaddr_ll *sll; #endif if (getifaddrs(&ifaddrs) == -1) return NULL; ifs = malloc(sizeof(*ifs)); if (ifs == NULL) return NULL; TAILQ_INIT(ifs); for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr != NULL) { #ifdef AF_LINK if (ifa->ifa_addr->sa_family != AF_LINK) continue; #elif AF_PACKET if (ifa->ifa_addr->sa_family != AF_PACKET) continue; #endif } /* Ensure that the interface name has settled */ if (!dev_initialized(ctx, ifa->ifa_name)) continue; /* It's possible for an interface to have >1 AF_LINK. * For our purposes, we use the first one. */ TAILQ_FOREACH(ifp, ifs, next) { if (strcmp(ifp->name, ifa->ifa_name) == 0) break; } if (ifp) continue; if (argc > 0) { for (i = 0; i < argc; i++) { #ifdef __linux__ /* Check the real interface name */ strlcpy(ifn, argv[i], sizeof(ifn)); p = strchr(ifn, ':'); if (p) *p = '\0'; if (strcmp(ifn, ifa->ifa_name) == 0) break; #else if (strcmp(argv[i], ifa->ifa_name) == 0) break; #endif } if (i == argc) continue; p = argv[i]; } else { p = ifa->ifa_name; /* -1 means we're discovering against a specific * interface, but we still need the below rules * to apply. */ if (argc == -1 && strcmp(argv[0], ifa->ifa_name) != 0) continue; } for (i = 0; i < ctx->ifdc; i++) if (!fnmatch(ctx->ifdv[i], p, 0)) break; if (i < ctx->ifdc) continue; for (i = 0; i < ctx->ifac; i++) if (!fnmatch(ctx->ifav[i], p, 0)) break; if (ctx->ifac && i == ctx->ifac) continue; if (if_vimaster(ifa->ifa_name) == 1) { syslog(argc ? LOG_ERR : LOG_DEBUG, "%s: is a Virtual Interface Master, skipping", ifa->ifa_name); continue; } ifp = calloc(1, sizeof(*ifp)); if (ifp == NULL) { syslog(LOG_ERR, "%s: %m", __func__); break; } ifp->ctx = ctx; strlcpy(ifp->name, p, sizeof(ifp->name)); ifp->flags = ifa->ifa_flags; /* Bring the interface up if not already */ if (!(ifp->flags & IFF_UP) #ifdef SIOCGIFMEDIA && carrier_status(ifp) != LINK_UNKNOWN #endif ) { if (up_interface(ifp) == 0) ctx->options |= DHCPCD_WAITUP; else syslog(LOG_ERR, "%s: up_interface: %m", ifp->name); } sdl_type = 0; /* Don't allow loopback unless explicit */ if (ifp->flags & IFF_LOOPBACK) { if (argc == 0 && ctx->ifac == 0) { free_interface(ifp); continue; } } else if (ifa->ifa_addr != NULL) { #ifdef AF_LINK sdl = (const struct sockaddr_dl *)(void *)ifa->ifa_addr; #ifdef IFLR_ACTIVE /* We need to check for active address */ strlcpy(iflr.iflr_name, ifp->name, sizeof(iflr.iflr_name)); memcpy(&iflr.addr, ifa->ifa_addr, MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr))); iflr.flags = IFLR_PREFIX; iflr.prefixlen = sdl->sdl_alen * NBBY; if (ioctl(s_link, SIOCGLIFADDR, &iflr) == -1 || !(iflr.flags & IFLR_ACTIVE)) { free_interface(ifp); continue; } #endif ifp->index = sdl->sdl_index; sdl_type = sdl->sdl_type; switch(sdl->sdl_type) { case IFT_BRIDGE: /* FALLTHROUGH */ case IFT_L2VLAN: /* FALLTHOUGH */ case IFT_L3IPVLAN: /* FALLTHROUGH */ case IFT_ETHER: ifp->family = ARPHRD_ETHER; break; case IFT_IEEE1394: ifp->family = ARPHRD_IEEE1394; break; #ifdef IFT_INFINIBAND case IFT_INFINIBAND: ifp->family = ARPHRD_INFINIBAND; break; #endif } ifp->hwlen = sdl->sdl_alen; #ifndef CLLADDR # define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen)) #endif memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen); #elif AF_PACKET sll = (const struct sockaddr_ll *)(void *)ifa->ifa_addr; ifp->index = sll->sll_ifindex; ifp->family = sdl_type = sll->sll_hatype; ifp->hwlen = sll->sll_halen; if (ifp->hwlen != 0) memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen); #endif } #ifdef __linux__ /* PPP addresses on Linux don't have hardware addresses */ else ifp->index = if_nametoindex(ifp->name); #endif /* We only work on ethernet by default */ if (!(ifp->flags & IFF_POINTOPOINT) && ifp->family != ARPHRD_ETHER) { if (argc == 0 && ctx->ifac == 0) { free_interface(ifp); continue; } switch (ifp->family) { case ARPHRD_IEEE1394: /* FALLTHROUGH */ case ARPHRD_INFINIBAND: /* We don't warn for supported families */ break; default: syslog(LOG_WARNING, "%s: unsupported interface type %.2x" ", falling back to ethernet", ifp->name, sdl_type); ifp->family = ARPHRD_ETHER; break; } } /* Handle any platform init for the interface */ if (if_init(ifp) == -1) { syslog(LOG_ERR, "%s: if_init: %m", p); free_interface(ifp); continue; } /* Ensure that the MTU is big enough for DHCP */ if (get_mtu(ifp->name) < MTU_MIN && set_mtu(ifp->name, MTU_MIN) == -1) { syslog(LOG_ERR, "%s: set_mtu: %m", p); free_interface(ifp); continue; } #ifdef SIOCGIFPRIORITY /* Respect the interface priority */ memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); if (ioctl(s_inet, SIOCGIFPRIORITY, &ifr) == 0) ifp->metric = ifr.ifr_metric; #else /* We reserve the 100 range for virtual interfaces, if and when * we can work them out. */ ifp->metric = 200 + ifp->index; if (getifssid(ifp->name, ifp->ssid) != -1) { ifp->wireless = 1; ifp->metric += 100; } #endif TAILQ_INSERT_TAIL(ifs, ifp, next); } for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; switch(ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: addr = (const struct sockaddr_in *) (void *)ifa->ifa_addr; net = (const struct sockaddr_in *) (void *)ifa->ifa_netmask; if (ifa->ifa_flags & IFF_POINTOPOINT) dst = (const struct sockaddr_in *) (void *)ifa->ifa_dstaddr; else dst = NULL; ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name, &addr->sin_addr, &net->sin_addr, dst ? &dst->sin_addr : NULL); break; #endif #ifdef INET6 case AF_INET6: sin6 = (const struct sockaddr_in6 *) (void *)ifa->ifa_addr; ifa_flags = in6_addr_flags(ifa->ifa_name, &sin6->sin6_addr); if (ifa_flags != -1) ipv6_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name, &sin6->sin6_addr, ifa_flags); break; #endif } } freeifaddrs(ifaddrs); #ifdef SIOCGIFPRIORITY close(s_inet); #endif #ifdef IFLR_ACTIVE close(s_link); #endif return ifs; }
/* * Get informtion about a server from the kernel * * Arguments: * ssp pointer to the server block * * Returns: * 0 server info is OK * errno server is not ready * */ int scsp_get_server_info(Scsp_server *ssp) { int i, len, mtu, rc, sel; struct atminfreq air; struct air_netif_rsp *netif_rsp = NULL; struct air_int_rsp *intf_rsp = NULL; struct air_cfg_rsp *cfg_rsp = NULL; struct sockaddr_in *ip_addr; Atm_addr_nsap *anp; /* * Make sure we're the server for the interface */ if (!scsp_is_atmarp_server(ssp->ss_intf)) { rc = EINVAL; goto server_info_done; } /* * Get the IP address and physical interface name * associated with the network interface */ UM_ZERO(&air, sizeof(struct atminfreq)); air.air_opcode = AIOCS_INF_NIF; strcpy(air.air_netif_intf, ssp->ss_intf); len = do_info_ioctl(&air, sizeof(struct air_netif_rsp)); if (len <= 0) { rc = EIO; goto server_info_done; } netif_rsp = (struct air_netif_rsp *)air.air_buf_addr; ip_addr = (struct sockaddr_in *)&netif_rsp->anp_proto_addr; if (ip_addr->sin_family != AF_INET || ip_addr->sin_addr.s_addr == 0) { rc = EADDRNOTAVAIL; goto server_info_done; } /* * Get the MTU for the network interface */ mtu = get_mtu(ssp->ss_intf); if (mtu < 0) { rc = EIO; goto server_info_done; } /* * Get the ATM address associated with the * physical interface */ UM_ZERO(&air, sizeof(struct atminfreq)); air.air_opcode = AIOCS_INF_INT; strcpy(air.air_int_intf, netif_rsp->anp_phy_intf); len = do_info_ioctl(&air, sizeof(struct air_int_rsp)); if (len <= 0) { rc = EIO; goto server_info_done; } intf_rsp = (struct air_int_rsp *)air.air_buf_addr; /* * Make sure we're running UNI signalling */ if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 && intf_rsp->anp_sig_proto != ATM_SIG_UNI31 && intf_rsp->anp_sig_proto != ATM_SIG_UNI40) { rc = EINVAL; goto server_info_done; } /* * Check the physical interface's state */ if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) { rc = EHOSTDOWN; goto server_info_done; } /* * Make sure the interface's address is valid */ if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR && !(intf_rsp->anp_addr.address_format == T_ATM_E164_ADDR && intf_rsp->anp_subaddr.address_format == T_ATM_ENDSYS_ADDR)) { rc = EINVAL; goto server_info_done; } /* * Find the selector byte value for the interface */ for (i=0; i<strlen(ssp->ss_intf); i++) { if (ssp->ss_intf[i] >= '0' && ssp->ss_intf[i] <= '9') break; } sel = atoi(&ssp->ss_intf[i]); /* * Get configuration information associated with the * physical interface */ UM_ZERO(&air, sizeof(struct atminfreq)); air.air_opcode = AIOCS_INF_CFG; strcpy(air.air_int_intf, netif_rsp->anp_phy_intf); len = do_info_ioctl(&air, sizeof(struct air_cfg_rsp)); if (len <= 0) { rc = EIO; goto server_info_done; } cfg_rsp = (struct air_cfg_rsp *)air.air_buf_addr; /* * Update the server entry */ UM_COPY(&ip_addr->sin_addr, ssp->ss_lsid.id, ssp->ss_id_len); ssp->ss_lsid.id_len = ssp->ss_id_len; ssp->ss_mtu = mtu + 8; ATM_ADDR_COPY(&intf_rsp->anp_addr, &ssp->ss_addr); ATM_ADDR_COPY(&intf_rsp->anp_subaddr, &ssp->ss_subaddr); if (ssp->ss_addr.address_format == T_ATM_ENDSYS_ADDR) { anp = (Atm_addr_nsap *)ssp->ss_addr.address; anp->aan_sel = sel; } else if (ssp->ss_addr.address_format == T_ATM_E164_ADDR && ssp->ss_subaddr.address_format == T_ATM_ENDSYS_ADDR) { anp = (Atm_addr_nsap *)ssp->ss_subaddr.address; anp->aan_sel = sel; } ssp->ss_media = cfg_rsp->acp_cfg.ac_media; rc = 0; /* * Free dynamic data */ server_info_done: if (netif_rsp) UM_FREE(netif_rsp); if (intf_rsp) UM_FREE(intf_rsp); if (cfg_rsp) UM_FREE(cfg_rsp); return(rc); }
JNIEXPORT jint JNICALL Java_eu_faircode_netguard_ServiceSinkhole_jni_1get_1mtu(JNIEnv *env, jobject instance) { return get_mtu(); }
int rdt_connect(struct in_addr dst, int scid, int dcid) { int n, fd; pid_t pid; struct sockaddr_un un; struct in_addr src; struct conn_info conn_info; if (signal(SIGINT, sig_hand) == SIG_ERR || signal(SIGHUP, sig_hand) == SIG_ERR || signal(SIGQUIT, sig_hand) == SIG_ERR) { err_sys("signal() error"); } src = get_addr(dst); pid = getpid(); /* allocate share area for send * and recv process. */ conn_alloc(); conn_info.cact = ACTIVE; conn_info.pid = pid; conn_info.src = conn_user->src = src; conn_info.dst = conn_user->dst = dst; conn_info.scid = conn_user->scid = scid; conn_info.dcid = conn_user->dcid = dcid; conn_user->sndfd = make_fifo(pid, "snd"); conn_user->rcvfd = make_fifo(pid, "rcv"); conn_user->sfd = make_sock(); conn_user->seq = conn_user->ack = 0; if (!mtu) { if (dev[0] == 0 && !get_dev(src, dev)) err_quit("can't get dev name"); mtu = get_mtu(dev); } n = min(mtu, 1500); conn_user->mss = n; if ((conn_user->sndpkt = malloc(n)) == NULL) err_sys("malloc() sndpkt error"); if ((conn_user->rcvpkt = malloc(n)) == NULL) err_sys("malloc() rcvpkt error"); if ((fd = ux_cli(RDT_UX_SOCK, &un)) < 0) err_sys("ux_cli() error"); n = sizeof(struct conn_info); if (sendto(fd, &conn_info, n, 0, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) != n) { err_sys("sendto() error"); } get_pkt(conn_user->sndfd, &conn_info, NULL, 0); conn_user->scid = conn_info.scid; if (rexmt_pkt(conn_user, RDT_REQ, NULL, 0) < 0) err_sys("rexmt_pkt() error"); fprintf(stderr, "rdt_connect() succeed\n"); pkt_debug((struct rdthdr *)conn_user->sndpkt); return(0); }