1/* 2 * Common hostapd/wpa_supplicant ctrl iface code. 3 * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> 4 * Copyright (c) 2015, Qualcomm Atheros, Inc. 5 * 6 * This software may be distributed under the terms of the BSD license. 7 * See README for more details. 8 */ 9 10#include "utils/includes.h" 11#include <netdb.h> 12#include <sys/un.h> 13 14#include "utils/common.h" 15#include "ctrl_iface_common.h" 16 17static int sockaddr_compare(struct sockaddr_storage *a, socklen_t a_len, 18 struct sockaddr_storage *b, socklen_t b_len) 19{ 20 if (a->ss_family != b->ss_family) 21 return 1; 22 23 switch (a->ss_family) { 24#ifdef CONFIG_CTRL_IFACE_UDP 25 case AF_INET: 26 { 27 struct sockaddr_in *in_a, *in_b; 28 29 in_a = (struct sockaddr_in *) a; 30 in_b = (struct sockaddr_in *) b; 31 32 if (in_a->sin_port != in_b->sin_port) 33 return 1; 34 if (in_a->sin_addr.s_addr != in_b->sin_addr.s_addr) 35 return 1; 36 break; 37 } 38 case AF_INET6: 39 { 40 struct sockaddr_in6 *in6_a, *in6_b; 41 42 in6_a = (struct sockaddr_in6 *) a; 43 in6_b = (struct sockaddr_in6 *) b; 44 45 if (in6_a->sin6_port != in6_b->sin6_port) 46 return 1; 47 if (os_memcmp(&in6_a->sin6_addr, &in6_b->sin6_addr, 48 sizeof(in6_a->sin6_addr)) != 0) 49 return 1; 50 break; 51 } 52#endif /* CONFIG_CTRL_IFACE_UDP */ 53#ifdef CONFIG_CTRL_IFACE_UNIX 54 case AF_UNIX: 55 { 56 struct sockaddr_un *u_a, *u_b; 57 58 u_a = (struct sockaddr_un *) a; 59 u_b = (struct sockaddr_un *) b; 60 61 if (a_len != b_len || 62 os_memcmp(u_a->sun_path, u_b->sun_path, 63 a_len - offsetof(struct sockaddr_un, sun_path)) 64 != 0) 65 return 1; 66 break; 67 } 68#endif /* CONFIG_CTRL_IFACE_UNIX */ 69 default: 70 return 1; 71 } 72 73 return 0; 74} 75 76 77void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock, 78 socklen_t socklen) 79{ 80 switch (sock->ss_family) { 81#ifdef CONFIG_CTRL_IFACE_UDP 82 case AF_INET: 83 case AF_INET6: 84 { 85 char host[NI_MAXHOST] = { 0 }; 86 char service[NI_MAXSERV] = { 0 }; 87 88 getnameinfo((struct sockaddr *) sock, socklen, 89 host, sizeof(host), 90 service, sizeof(service), 91 NI_NUMERICHOST); 92 93 wpa_printf(level, "%s %s:%s", msg, host, service); 94 break; 95 } 96#endif /* CONFIG_CTRL_IFACE_UDP */ 97#ifdef CONFIG_CTRL_IFACE_UNIX 98 case AF_UNIX: 99 { 100 char addr_txt[200]; 101 102 printf_encode(addr_txt, sizeof(addr_txt), 103 (u8 *) ((struct sockaddr_un *) sock)->sun_path, 104 socklen - offsetof(struct sockaddr_un, sun_path)); 105 wpa_printf(level, "%s %s", msg, addr_txt); 106 break; 107 } 108#endif /* CONFIG_CTRL_IFACE_UNIX */ 109 default: 110 wpa_printf(level, "%s", msg); 111 break; 112 } 113} 114 115 116int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from, 117 socklen_t fromlen) 118{ 119 struct wpa_ctrl_dst *dst; 120 121 dst = os_zalloc(sizeof(*dst)); 122 if (dst == NULL) 123 return -1; 124 os_memcpy(&dst->addr, from, fromlen); 125 dst->addrlen = fromlen; 126 dst->debug_level = MSG_INFO; 127 dl_list_add(ctrl_dst, &dst->list); 128 129 sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor attached", from, fromlen); 130 return 0; 131} 132 133 134int ctrl_iface_detach(struct dl_list *ctrl_dst, struct sockaddr_storage *from, 135 socklen_t fromlen) 136{ 137 struct wpa_ctrl_dst *dst; 138 139 dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) { 140 if (!sockaddr_compare(from, fromlen, 141 &dst->addr, dst->addrlen)) { 142 sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor detached", 143 from, fromlen); 144 dl_list_del(&dst->list); 145 os_free(dst); 146 return 0; 147 } 148 } 149 150 return -1; 151} 152 153 154int ctrl_iface_level(struct dl_list *ctrl_dst, struct sockaddr_storage *from, 155 socklen_t fromlen, const char *level) 156{ 157 struct wpa_ctrl_dst *dst; 158 159 wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 160 161 dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) { 162 if (!sockaddr_compare(from, fromlen, 163 &dst->addr, dst->addrlen)) { 164 sockaddr_print(MSG_DEBUG, 165 "CTRL_IFACE changed monitor level", 166 from, fromlen); 167 dst->debug_level = atoi(level); 168 return 0; 169 } 170 } 171 172 return -1; 173} 174