static FAR struct uip_driver_s *netdev_finddevice(const uip_ipaddr_t addr) { struct uip_driver_s *dev; netdev_semtake(); for (dev = g_netdevices; dev; dev = dev->flink) { if (uip_ipaddr_maskcmp(dev->d_ipaddr, addr, dev->d_netmask)) { netdev_semgive(); return dev; } } netdev_semgive(); return NULL; }
FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t *raddr) { struct uip_driver_s *dev; if (raddr) { netdev_semtake(); for (dev = g_netdevices; dev; dev = dev->flink) { if (netdev_maskcmp(&dev->d_ipaddr, raddr, &dev->d_netmask)) { netdev_semgive(); return dev; } } netdev_semgive(); } return NULL; }
int netdev_count(void) { struct uip_driver_s *dev; int ndev; netdev_semtake(); for (dev = g_netdevices, ndev = 0; dev; dev = dev->flink, ndev++); netdev_semgive(); return ndev; }
int netdev_unregister(FAR struct uip_driver_s *dev) { struct uip_driver_s *prev; struct uip_driver_s *curr; if (dev) { netdev_semtake(); /* Find the device in the list of known network devices */ for (prev = NULL, curr = g_netdevices; curr && curr != dev; prev = curr, curr = curr->flink); /* Remove the device to the list of known network devices */ if (curr) { /* Where was the entry */ if (prev) { /* The entry was in the middle or at the end of the list */ prev->flink = curr->flink; } else { /* The entry was at the beginning of the list */ g_netdevices = curr; } curr->flink = NULL; } netdev_semgive(); #ifdef CONFIG_NET_ETHERNET nlldbg("Unregistered MAC: %02x:%02x:%02x:%02x:%02x:%02x as dev: %s\n", dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1], dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3], dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5], dev->d_ifname); #else nlldbg("Registered dev: %s\n", dev->d_ifname); #endif return OK; } return -EINVAL; }
int netdev_foreach(netdev_callback_t callback, void *arg) { struct uip_driver_s *dev; int ret = 0; if (callback) { netdev_semtake(); for (dev = g_netdevices; dev; dev = dev->flink) { if (callback(dev, arg) != 0) { ret = 1; break; } } netdev_semgive(); } return ret; }
int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr, FAR socklen_t *addrlen) { FAR struct net_driver_s *dev; #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) FAR struct sockaddr_in *outaddr = (FAR struct sockaddr_in *)addr; #endif #ifdef CONFIG_NETDEV_MULTINIC in_addr_t lipaddr; in_addr_t ripaddr; #endif /* Check if enough space has been provided for the full address */ if (*addrlen < sizeof(struct sockaddr_in)) { /* This function is supposed to return the partial address if * a smaller buffer has been provided. This support has not * been implemented. */ return -ENOSYS; } /* Set the port number */ switch (psock->s_type) { #ifdef CONFIG_NET_TCP case SOCK_STREAM: { FAR struct tcp_conn_s *tcp_conn = (FAR struct tcp_conn_s *)psock->s_conn; outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */ #ifdef CONFIG_NETDEV_MULTINIC lipaddr = tcp_conn->u.ipv4.laddr; ripaddr = tcp_conn->u.ipv4.raddr; #endif } break; #endif #ifdef CONFIG_NET_UDP case SOCK_DGRAM: { FAR struct udp_conn_s *udp_conn = (FAR struct udp_conn_s *)psock->s_conn; outaddr->sin_port = udp_conn->lport; /* Already in network byte order */ #ifdef CONFIG_NETDEV_MULTINIC lipaddr = udp_conn->u.ipv4.laddr; ripaddr = udp_conn->u.ipv4.raddr; #endif } break; #endif default: return -EOPNOTSUPP; } /* The socket/connection does not know its IP address unless * CONFIG_NETDEV_MULTINIC is selected. Otherwise the design supports only * a single network device and only the network device knows the IP address. */ netdev_semtake(); #ifdef CONFIG_NETDEV_MULTINIC /* Find the device matching the IPv4 address in the connection structure */ dev = netdev_findby_ipv4addr(lipaddr, ripaddr); #else /* There is only one, the first network device in the list. */ dev = g_netdevices; #endif if (!dev) { netdev_semgive(); return -EINVAL; } /* Set the address family and the IP address */ #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) outaddr->sin_family = AF_INET; outaddr->sin_addr.s_addr = dev->d_ipaddr; *addrlen = sizeof(struct sockaddr_in); #endif netdev_semgive(); /* Return success */ return OK; }
int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) { FAR struct socket *psock = sockfd_socket(sockfd); FAR struct uip_driver_s *dev; #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) #ifdef CONFIG_NET_IPv6 FAR struct sockaddr_in6 *outaddr = (FAR struct sockaddr_in6 *)addr; #else FAR struct sockaddr_in *outaddr = (FAR struct sockaddr_in *)addr; #endif #endif int err; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { err = EBADF; goto errout; } /* Some sanity checking... Shouldn't need this on a buckled up embedded * system (?) */ #ifdef CONFIG_DEBUG if (!addr || !addrlen) { err = EINVAL; goto errout; } #endif /* Check if enough space has been provided for the full address */ #ifdef CONFIG_NET_IPv6 if (*addrlen < sizeof(struct sockaddr_in6)) #else if (*addrlen < sizeof(struct sockaddr_in)) #endif { /* This function is supposed to return the partial address if * a smaller buffer has been provided. This support has not * been implemented. */ err = ENOSYS; goto errout; } /* Set the port number */ switch (psock->s_type) { #ifdef CONFIG_NET_TCP case SOCK_STREAM: { struct uip_conn *tcp_conn = (struct uip_conn *)psock->s_conn; outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */ } break; #endif #ifdef CONFIG_NET_UDP case SOCK_DGRAM: { struct uip_udp_conn *udp_conn = (struct uip_udp_conn *)psock->s_conn; outaddr->sin_port = udp_conn->lport; /* Already in network byte order */ } break; #endif default: err = EOPNOTSUPP; goto errout; } /* ISSUE: As of this writing, the socket/connection does not know its IP * address. This is because the uIP design is only intended to support * a single network device and, therefore, only the network device knows * the IP address. * * Right now, we can just pick the first network device. But that may * not work in the future. */ netdev_semtake(); dev = g_netdevices; if (!dev) { netdev_semgive(); err = EINVAL; goto errout; } /* Set the address family and the IP address */ #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) #ifdef CONFIG_NET_IPv6 #error "Not big enough for IPv6 address" outaddr->sin_family = AF_INET6; memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipaddr, 16); *addrlen = sizeof(struct sockaddr_in6); #else outaddr->sin_family = AF_INET; outaddr->sin_addr.s_addr = dev->d_ipaddr; *addrlen = sizeof(struct sockaddr_in); #endif #endif netdev_semgive(); /* Return success */ return OK; errout: set_errno(err); return ERROR; }
int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype) { FAR const char *devfmt; #ifdef CONFIG_NET_USER_DEVFMT FAR const char devfmt_str[IFNAMSIZ]; #endif int devnum; if (dev) { #ifdef CONFIG_NET_MULTILINK /* We are supporting multiple network devices and using different link * level protocols. Set the protocol usd by the device and the size * level protocols. Set the protocol used by the device and the size * of the link header used by this protocol. */ switch (lltype) { #ifdef CONFIG_NET_ETHERNET case NET_LL_ETHERNET: /* Ethernet */ dev->d_llhdrlen = ETH_HDRLEN; dev->d_mtu = CONFIG_NET_ETH_MTU; #ifdef CONFIG_NET_TCP_STACK dev->d_recvwndo = CONFIG_NET_ETH_TCP_RECVWNDO; #endif devfmt = NETDEV_ETH_FORMAT; break; #endif #ifdef CONFIG_NET_SLIP case NET_LL_SLIP: /* Serial Line Internet Protocol (SLIP) */ dev->d_llhdrlen = 0; dev->d_mtu = CONFIG_NET_SLIP_MTU; #ifdef CONFIG_NET_TCP_STACK dev->d_recvwndo = CONFIG_NET_SLIP_TCP_RECVWNDO; #endif devfmt = NETDEV_SLIP_FORMAT; break; #endif #ifdef CONFIG_NET_TUN case NET_LL_TUN: /* Virtual Network Device (TUN) */ dev->d_llhdrlen = 0; dev->d_mtu = CONFIG_NET_TUN_MTU; #ifdef CONFIG_NET_TCP dev->d_recvwndo = CONFIG_NET_TUN_TCP_RECVWNDO; #endif devfmt = NETDEV_TUN_FORMAT; break; #endif #if 0 /* REVISIT: Not yet supported */ case NET_LL_PPP: /* Point-to-Point Protocol (PPP) */ dev->d_llhdrlen = 0; dev->d_mtu = CONFIG_NET_PPP_MTU; #ifdef CONFIG_NET_TCP_STACK dev->d_recvwndo = CONFIG_NET_PPP_TCP_RECVWNDO; #endif devfmt = NETDEV_PPP_FORMAT; break; #endif default: nlldbg("ERROR: Unrecognized link type: %d\n", lltype); return -EINVAL; } /* Remember the verified link type */ dev->d_lltype = (uint8_t)lltype; #else /* Use the default device name */ devfmt = NETDEV_DEFAULT_FORMAT; #endif /* Get the next available device number and sssign a device name to * the interface */ netdev_semtake(); #ifdef CONFIG_NET_MULTILINK devnum = find_devnum(devfmt); #else devnum = g_next_devnum++; #endif #ifdef CONFIG_NET_USER_DEVFMT if (*dev->d_ifname) { strncpy(devfmt_str, dev->d_ifname, IFNAMSIZ); devfmt = devfmt_str; } #endif snprintf(dev->d_ifname, IFNAMSIZ, devfmt, devnum ); /* Add the device to the list of known network devices */ dev->flink = g_netdevices; g_netdevices = dev; /* Configure the device for IGMP support */ #ifdef CONFIG_NET_IGMP igmp_devinit(dev); #endif netdev_semgive(); #ifdef CONFIG_NET_ETHERNET nlldbg("Registered MAC: %02x:%02x:%02x:%02x:%02x:%02x as dev: %s\n", dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1], dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3], dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5], dev->d_ifname); #else nlldbg("Registered dev: %s\n", dev->d_ifname); #endif return OK; } return -EINVAL; }
FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t addr) { struct uip_driver_s *dev; #ifdef CONFIG_NET_ROUTE uip_ipaddr_t router; int ret; #endif /* First, see if the address maps to the a local network */ dev = netdev_finddevice(addr); if (dev) { return dev; } /* No.. The address lies on an external network */ #ifdef CONFIG_NET_ROUTE /* If we have a routing table, then perhaps we can find the the local * address of a router that can forward packets to the external network. */ #ifdef CONFIG_NET_IPv6 ret = net_router(addr, router); #else ret = net_router(addr, &router); #endif if (ret >= 0) { /* Success... try to find the network device associated with the local * router address */ dev = netdev_finddevice(router); if (dev) { return dev; } } #endif /* CONFIG_NET_ROUTE */ /* The above lookup will fail if the packet is being sent out of our * out subnet to a router and there is no routing information. * * However, if there is only a single, registered network interface, then * the decision is pretty easy. Use that device and its default router * address. */ netdev_semtake(); if (g_netdevices && !g_netdevices->flink) { dev = g_netdevices; } netdev_semgive(); /* If we will did not find the network device, then we might as well fail * because we are not configured properly to determine the route to the * target. */ return dev; }