📄 wps_upnp.c
字号:
wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription %p started with %s", s, callback_urls); os_free(callback_urls); /* Schedule sending this */ event_send_all_later(sm); return s;}/* subscription_renew -- find subscription and reset timeout */struct subscription * subscription_renew(struct upnp_wps_device_sm *sm, const u8 uuid[UUID_LEN]){ time_t now = time(NULL); time_t expire = now + UPNP_SUBSCRIBE_SEC; struct subscription *s = subscription_find(sm, uuid); if (s == NULL) return NULL; wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription renewed"); subscription_unlink(s); s->timeout_time = expire; /* add back to end of list, since it now has highest expiry */ subscription_link_to_end(s); return s;}/** * upnp_wps_device_send_wlan_event - Event notification * @sm: WPS UPnP state machine from upnp_wps_device_init() * @from_mac_addr: Source (Enrollee) MAC address for the event * @ev_type: Event type * @msg: Event data * Returns: 0 on success, -1 on failure * * Tell external Registrars (UPnP control points) that something happened. In * particular, events include WPS messages from clients that are proxied to * external Registrars. */int upnp_wps_device_send_wlan_event(struct upnp_wps_device_sm *sm, const u8 from_mac_addr[ETH_ALEN], enum upnp_wps_wlanevent_type ev_type, const struct wpabuf *msg){ int ret = -1; char type[2]; const u8 *mac = from_mac_addr; char mac_text[18]; u8 *raw = NULL; size_t raw_len; char *val; size_t val_len; int pos = 0; if (!sm) goto fail; os_snprintf(type, sizeof(type), "%1u", ev_type); raw_len = 1 + 17 + (msg ? wpabuf_len(msg) : 0); raw = os_zalloc(raw_len); if (!raw) goto fail; *(raw + pos) = (u8) ev_type; pos += 1; os_snprintf(mac_text, sizeof(mac_text), MACSTR, MAC2STR(mac)); wpa_printf(MSG_DEBUG, "WPS UPnP: Proxying WLANEvent from %s", mac_text); os_memcpy(raw + pos, mac_text, 17); pos += 17; if (msg) { os_memcpy(raw + pos, wpabuf_head(msg), wpabuf_len(msg)); pos += wpabuf_len(msg); } raw_len = pos; val = (char *) base64_encode(raw, raw_len, &val_len); if (val == NULL) goto fail; os_free(sm->wlanevent); sm->wlanevent = val; upnp_wps_device_send_event(sm); ret = 0;fail: os_free(raw); return ret;}#ifdef __FreeBSD__#include <sys/sysctl.h>#include <net/route.h>#include <net/if_dl.h>static int eth_get(const char *device, u8 ea[ETH_ALEN]){ struct if_msghdr *ifm; struct sockaddr_dl *sdl; u_char *p, *buf; size_t len; int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }; if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) return -1; if ((buf = os_malloc(len)) == NULL) return -1; if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { os_free(buf); return -1; } for (p = buf; p < buf + len; p += ifm->ifm_msglen) { ifm = (struct if_msghdr *)p; sdl = (struct sockaddr_dl *)(ifm + 1); if (ifm->ifm_type != RTM_IFINFO || (ifm->ifm_addrs & RTA_IFP) == 0) continue; if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 || os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0) continue; os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen); break; } os_free(buf); if (p >= buf + len) { errno = ESRCH; return -1; } return 0;}#endif /* __FreeBSD__ *//** * get_netif_info - Get hw and IP addresses for network device * @net_if: Selected network interface name * @ip_addr: Buffer for returning IP address in network byte order * @ip_addr_text: Buffer for returning a pointer to allocated IP address text * @mac: Buffer for returning MAC address * @mac_addr_text: Buffer for returning allocated MAC address text * Returns: 0 on success, -1 on failure */static int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, u8 mac[ETH_ALEN], char **mac_addr_text){ struct ifreq req; int sock = -1; struct sockaddr_in *addr; struct in_addr in_addr; *ip_addr_text = os_zalloc(16); *mac_addr_text = os_zalloc(18); if (*ip_addr_text == NULL || *mac_addr_text == NULL) goto fail; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) goto fail; os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name)); if (ioctl(sock, SIOCGIFADDR, &req) < 0) { wpa_printf(MSG_ERROR, "WPS UPnP: SIOCGIFADDR failed: %d (%s)", errno, strerror(errno)); goto fail; } addr = (void *) &req.ifr_addr; *ip_addr = addr->sin_addr.s_addr; in_addr.s_addr = *ip_addr; os_snprintf(*ip_addr_text, 16, "%s", inet_ntoa(in_addr));#ifdef __linux__ os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name)); if (ioctl(sock, SIOCGIFHWADDR, &req) < 0) { wpa_printf(MSG_ERROR, "WPS UPnP: SIOCGIFHWADDR failed: " "%d (%s)", errno, strerror(errno)); goto fail; } os_memcpy(mac, req.ifr_addr.sa_data, 6);#elif defined(__FreeBSD__) if (eth_get(net_if, mac) < 0) { wpa_printf(MSG_ERROR, "WPS UPnP: Failed to get MAC address"); goto fail; }#else#error MAC address fetch not implemented#endif os_snprintf(*mac_addr_text, 18, MACSTR, MAC2STR(req.ifr_addr.sa_data)); close(sock); return 0;fail: if (sock >= 0) close(sock); os_free(*ip_addr_text); *ip_addr_text = NULL; os_free(*mac_addr_text); *mac_addr_text = NULL; return -1;}/** * upnp_wps_device_stop - Stop WPS UPnP operations on an interface * @sm: WPS UPnP state machine from upnp_wps_device_init() */void upnp_wps_device_stop(struct upnp_wps_device_sm *sm){ if (!sm || !sm->started) return; wpa_printf(MSG_DEBUG, "WPS UPnP: Stop device"); web_listener_stop(sm); while (sm->web_connections) web_connection_stop(sm->web_connections); while (sm->msearch_replies) msearchreply_state_machine_stop(sm->msearch_replies); while (sm->subscriptions) { struct subscription *s = sm->subscriptions; subscription_unlink(s); subscription_destroy(s); } advertisement_state_machine_stop(sm); /* TODO: send byebye notifications */ event_send_stop_all(sm); os_free(sm->wlanevent); sm->wlanevent = NULL; os_free(sm->net_if); sm->net_if = NULL; os_free(sm->mac_addr_text); sm->mac_addr_text = NULL; os_free(sm->ip_addr_text); sm->ip_addr_text = NULL; if (sm->multicast_sd >= 0) close(sm->multicast_sd); sm->multicast_sd = -1; ssdp_listener_stop(sm); sm->started = 0;}/** * upnp_wps_device_start - Start WPS UPnP operations on an interface * @sm: WPS UPnP state machine from upnp_wps_device_init() * @net_if: Selected network interface name * Returns: 0 on success, -1 on failure */int upnp_wps_device_start(struct upnp_wps_device_sm *sm, char *net_if){ if (!sm || !net_if) return -1; if (sm->started) upnp_wps_device_stop(sm); sm->net_if = strdup(net_if); sm->multicast_sd = -1; sm->ssdp_sd = -1; sm->started = 1; sm->advertise_count = 0; /* Fix up linux multicast handling */ if (add_ssdp_network(net_if)) goto fail; /* Determine which IP and mac address we're using */ if (get_netif_info(net_if, &sm->ip_addr, &sm->ip_addr_text, sm->mac_addr, &sm->mac_addr_text)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " "for %s. Does it have IP address?", net_if); goto fail; } /* Listen for incoming TCP connections so that others * can fetch our "xml files" from us. */ if (web_listener_start(sm)) goto fail; /* Set up for receiving discovery (UDP) packets */ if (ssdp_listener_start(sm)) goto fail; /* Set up for sending multicast */ if (ssdp_open_multicast(sm) < 0) goto fail; /* * Broadcast NOTIFY messages to let the world know we exist. * This is done via a state machine since the messages should not be * all sent out at once. */ if (advertisement_state_machine_start(sm)) goto fail; return 0;fail: upnp_wps_device_stop(sm); return -1;}/** * upnp_wps_device_deinit - Deinitialize WPS UPnP * @sm: WPS UPnP state machine from upnp_wps_device_init() */void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm){ if (!sm) return; upnp_wps_device_stop(sm); if (sm->peer.wps) wps_deinit(sm->peer.wps); os_free(sm->root_dir); os_free(sm->desc_url); os_free(sm->ctx); os_free(sm);}/** * upnp_wps_device_init - Initialize WPS UPnP * @ctx: callback table; we must eventually free it * @wps: Pointer to longterm WPS context * @priv: External context data that will be used in callbacks * Returns: WPS UPnP state or %NULL on failure */struct upnp_wps_device_sm *upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps, void *priv){ struct upnp_wps_device_sm *sm; sm = os_zalloc(sizeof(*sm)); if (!sm) { wpa_printf(MSG_ERROR, "WPS UPnP: upnp_wps_device_init failed"); return NULL; } sm->ctx = ctx; sm->wps = wps; sm->priv = priv; return sm;}/** * upnp_wps_subscribers - Check whether there are any event subscribers * @sm: WPS UPnP state machine from upnp_wps_device_init() * Returns: 0 if no subscribers, 1 if subscribers */int upnp_wps_subscribers(struct upnp_wps_device_sm *sm){ return sm->subscriptions != NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -