Line data Source code
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 :
17 15243 : static int sockaddr_compare(struct sockaddr_storage *a, socklen_t a_len,
18 : struct sockaddr_storage *b, socklen_t b_len)
19 : {
20 15243 : if (a->ss_family != b->ss_family)
21 0 : return 1;
22 :
23 15243 : 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 15243 : u_a = (struct sockaddr_un *) a;
59 15243 : u_b = (struct sockaddr_un *) b;
60 :
61 30478 : if (a_len != b_len ||
62 15235 : os_memcmp(u_a->sun_path, u_b->sun_path,
63 : a_len - offsetof(struct sockaddr_un, sun_path))
64 : != 0)
65 639 : return 1;
66 14604 : break;
67 : }
68 : #endif /* CONFIG_CTRL_IFACE_UNIX */
69 : default:
70 0 : return 1;
71 : }
72 :
73 14604 : return 0;
74 : }
75 :
76 :
77 270924 : void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock,
78 : socklen_t socklen)
79 : {
80 270924 : 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 541848 : printf_encode(addr_txt, sizeof(addr_txt),
103 270924 : (u8 *) ((struct sockaddr_un *) sock)->sun_path,
104 : socklen - offsetof(struct sockaddr_un, sun_path));
105 270924 : wpa_printf(level, "%s %s", msg, addr_txt);
106 270924 : break;
107 : }
108 : #endif /* CONFIG_CTRL_IFACE_UNIX */
109 : default:
110 0 : wpa_printf(level, "%s", msg);
111 0 : break;
112 : }
113 270924 : }
114 :
115 :
116 14759 : int 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 14759 : dst = os_zalloc(sizeof(*dst));
122 14759 : if (dst == NULL)
123 8 : return -1;
124 14751 : os_memcpy(&dst->addr, from, fromlen);
125 14751 : dst->addrlen = fromlen;
126 14751 : dst->debug_level = MSG_INFO;
127 14751 : dl_list_add(ctrl_dst, &dst->list);
128 :
129 14751 : sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor attached", from, fromlen);
130 14751 : return 0;
131 : }
132 :
133 :
134 14614 : int 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 15251 : dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
140 15239 : if (!sockaddr_compare(from, fromlen,
141 : &dst->addr, dst->addrlen)) {
142 14602 : sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor detached",
143 : from, fromlen);
144 14602 : dl_list_del(&dst->list);
145 14602 : os_free(dst);
146 14602 : return 0;
147 : }
148 : }
149 :
150 12 : return -1;
151 : }
152 :
153 :
154 4 : int 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 4 : wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
160 :
161 6 : dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
162 4 : if (!sockaddr_compare(from, fromlen,
163 : &dst->addr, dst->addrlen)) {
164 2 : sockaddr_print(MSG_DEBUG,
165 : "CTRL_IFACE changed monitor level",
166 : from, fromlen);
167 2 : dst->debug_level = atoi(level);
168 2 : return 0;
169 : }
170 : }
171 :
172 2 : return -1;
173 : }
|