libiwinfo: add restricted flag for freqlist
[project/luci.git] / contrib / fwd / src / fwd_addr.c
1 /*
2  * fwd - OpenWrt firewall daemon - rtnetlink communication
3  *
4  *   Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
5  *
6  * The fwd program is free software: you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License version 2
8  * as published by the Free Software Foundation.
9  *
10  * The fwd program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with the fwd program. If not, see http://www.gnu.org/licenses/.
17  */
18
19
20 #include "fwd.h"
21 #include "fwd_addr.h"
22 #include "fwd_utils.h"
23
24 struct fwd_addr * fwd_get_addrs(int fd, int family)
25 {
26         struct {
27                   struct nlmsghdr n;
28                   struct ifaddrmsg r;
29         } req;
30
31         int offlen;
32         int rtattrlen;
33         int dump_done;
34         char buf[16384];
35
36         struct rtattr *rta;
37         struct rtattr *rtatp;
38         struct nlmsghdr *nlmp;
39         struct ifaddrmsg *rtmp;
40
41         struct fwd_addr *head, *entry;
42
43         /* Build request */
44         memset(&req, 0, sizeof(req));
45         req.n.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
46         req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
47         req.n.nlmsg_type  = RTM_GETADDR;
48         req.r.ifa_family  = family;
49
50         rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.n.nlmsg_len));
51         rta->rta_len = RTA_LENGTH(family == AF_INET ? 4 : 16);
52
53         head = entry = NULL;
54
55         /* Send request */
56         if( send(fd, &req, sizeof(req), 0) <= 0 )
57                 goto error;
58
59         /* Receive responses */
60         for( dump_done = 0; !dump_done; )
61         {
62                 if( (offlen = recv(fd, buf, sizeof(buf), 0)) <= 0 )
63                         goto error;
64
65                 /* Parse message */
66                 for(nlmp = (struct nlmsghdr *)buf; offlen > sizeof(*nlmp);)
67                 {
68                         /* Dump finished? */
69                         if( nlmp->nlmsg_type == NLMSG_DONE )
70                         {
71                                 dump_done = 1;
72                                 break;
73                         }
74
75                         int len = nlmp->nlmsg_len;
76                         int req_len = len - sizeof(*nlmp);
77
78                         if( req_len<0 || len>offlen )
79                                 goto error;
80
81                         if( !NLMSG_OK(nlmp, offlen) )
82                                 goto error;
83
84                         rtmp  = (struct ifaddrmsg *) NLMSG_DATA(nlmp);
85                         rtatp = (struct rtattr *) IFA_RTA(rtmp);
86
87                         if( !(entry = fwd_alloc_ptr(struct fwd_addr)) )
88                                 goto error;
89
90                         entry->index = rtmp->ifa_index;
91                         if_indextoname(rtmp->ifa_index, (char *)&entry->ifname);
92
93                         rtattrlen = IFA_PAYLOAD(nlmp);
94
95                         for( ; RTA_OK(rtatp, rtattrlen); rtatp = RTA_NEXT(rtatp, rtattrlen) )
96                         {
97                                 if( rtatp->rta_type == IFA_ADDRESS )
98                                 {
99                                         memcpy(&entry->ipaddr.addr, (char *) RTA_DATA(rtatp), rtatp->rta_len);
100                                         entry->ipaddr.prefix = rtmp->ifa_prefixlen;
101                                         entry->family = family;
102                                 }
103                                 else if( rtatp->rta_type == IFA_LABEL)
104                                 {
105                                         memcpy(&entry->label, (char *) RTA_DATA(rtatp), rtatp->rta_len);
106                                 }
107                         }
108
109                         entry->next = head;
110                         head = entry;
111
112                         offlen -= NLMSG_ALIGN(len);
113                         nlmp = (struct nlmsghdr*)((char*)nlmp + NLMSG_ALIGN(len));
114                 }
115         }
116
117         return head;
118
119
120         error:
121
122         fwd_free_addrs(head);
123         head = entry = NULL;
124
125         return NULL;
126 }
127
128 struct fwd_cidr * fwd_lookup_addr(struct fwd_addr *head, const char *ifname)
129 {
130         struct fwd_addr *entry;
131
132         for( entry = head; entry; entry = entry->next )
133                 if( !strncmp(entry->ifname, ifname, IFNAMSIZ) )
134                         return &entry->ipaddr;
135
136         return NULL;
137 }
138
139 void fwd_free_addrs(struct fwd_addr *head)
140 {
141         struct fwd_addr *entry = head;
142
143         while( entry != NULL )
144         {
145                 head = entry->next;
146                 free(entry);
147                 entry = head;
148         }
149
150         head = entry = NULL;
151 }
152
153 struct fwd_addr * fwd_append_addrs(struct fwd_addr *head, struct fwd_addr *add)
154 {
155         struct fwd_addr *entry = head;
156
157         while( entry->next != NULL )
158                 entry = entry->next;
159
160         return (entry->next = add);
161 }
162