blob: 2835a32a733e3cef81e4b116bb188f34f4043350 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#include <sys/types.h>
2#include <sys/stat.h>
3#include <unistd.h>
4#include <stdlib.h>
5#include <errno.h>
6#include <stdio.h>
7#include <fcntl.h>
8#include <string.h>
9
10#include "piped.h"
11#include "piped_uci.h"
12#include "piped_util.h"
13#include "piped_nw.h"
14#include "piped_dhcp.h"
15#include "piped_dns.h"
16
17extern struct piped pd;
18
19static int pd_dhcp_set_limit(struct pd_context *pdc, int start_second, int start_third, int start, int limit)
20{
21 char startb[16];
22 char limitb[4];
23 struct uci_context *c = pdc->c;
24
25 if (start != 255 && start != 0) {
26 sprintf(startb, "%d", start);
27 } else {
28 if (start_third != 255 && start_third != 0)
29 sprintf(startb, "%d.%d", start_third, start);
30 else
31 sprintf(startb, "%d.%d.%d", start_second, start_third, start);
32 }
33 sprintf(limitb, "%d", limit);
34
35 if (pd_uci_set_opt(c, UCI_PKG_DHCP, UCI_SEC_LAN, UCI_OPT_START,
36 startb)) {
37 PD_ERR(pd_dhcp_set_limit, "pd_uci_set_opt failed %s\n", startb);
38 return 1;
39 }
40 if (pd_uci_set_opt(c, UCI_PKG_DHCP, UCI_SEC_LAN, UCI_OPT_LIMIT,
41 limitb)) {
42 PD_ERR(pd_dhcp_set_limit1, "pd_uci_set_opt failed %s\n", limitb);
43 return 1;
44 }
45
46 return 0;
47}
48
49static void pd_fast_dhcp_reply(char *ipaddr)
50{
51 char cmd[100] = {0};
52 char buf[10] = {0};
53 int vlan_or_eth = 0;
54 FILE *fp = NULL;
55 static char saved_ipaddr[MAX_IP_STR_LEN] = {0};
56 char *line = NULL;
57
58 pd_system("cat /sys/kernel/mpipe/devices/all | grep ccinet | grep Up4 | wc -l > /tmp/piped_count");
59
60 fp = fopen("/tmp/piped_count", "r");
61 if (!fp)
62 return;
63
64 line = fgets(buf, sizeof(buf), fp);
65 if (!line) {
66 fclose(fp);
67 return;
68 }
69 fclose(fp);
70 if (atoi(buf) > 1)
71 vlan_or_eth = 1;
72
73 if (vlan_or_eth) {
74 pd_system("uci set dhcp.@dnsmasq[0].readethers=0 && uci commit dhcp");
75 return;
76 }
77
78 if (!strncasecmp(ipaddr, saved_ipaddr, MAX_IP_STR_LEN))
79 return;
80
81 pd_system("head -n 1 /etc/ethers | cut -c -17 > /tmp/piped_ethers");
82 sprintf(cmd, "sed -i 's/$/& %s/g' /tmp/piped_ethers", ipaddr);
83 pd_system(cmd);
84 pd_system("cat /tmp/piped_ethers > /etc/ethers");
85 pd_system("uci set dhcp.@dnsmasq[0].readethers=1 && uci commit dhcp");
86 memcpy(saved_ipaddr, ipaddr, MAX_IP_STR_LEN);
87 return;
88}
89
90static int pd_dhcp_add_del_snmask(struct pd_context *pdc, bool add, int last_oct, int third_oct )
91{
92 struct uci_context *c = pdc->c;
93 char options[MAX_DHCP_OPT_STR_LEN];
94
95 strcpy(options, UCI_DHCP_OPTNUM_SNMASK);
96 strcat(options, ",");
97 if (last_oct != 255 && last_oct != 0)
98 strcat(options, UCI_DHCP_DFLT_SNMASK);
99 else {
100 if (third_oct != 255 && third_oct != 0)
101 strcat(options, UCI_DHCP_DFLT_SNMASK1);
102 else
103 strcat(options, UCI_DHCP_DFLT_SNMASK2);
104 }
105
106 if (add && pd_uci_add_list(c, UCI_PKG_DHCP, UCI_SEC_LAN,
107 UCI_OPT_DHCP_OPT, options)) {
108 PD_ERR(pd_dhcp_add_del_snmask, "pd_uci_add_list failed %s\n", options);
109 return 1;
110 } else if (!add && pd_uci_del_from_list(c, UCI_PKG_DHCP, UCI_SEC_LAN,
111 UCI_OPT_DHCP_OPT, options)) {
112 PD_ERR(pd_dhcp_add_del_snmask1, "pd_uci_del_from_list failed %s\n", options);
113 return 1;
114 }
115
116 return 0;
117}
118
119static int pd_dhcp_add_del_gw(struct pd_context *pdc, char *gw, bool add)
120{
121 struct uci_context *c = pdc->c;
122 char options[MAX_DHCP_OPT_STR_LEN];
123 size_t options_len, gw_len;
124
125 strcpy(options, UCI_DHCP_OPTNUM_GW);
126 strcat(options, ",");
127 options_len = strlen(options);
128 gw_len = strlen(gw);
129 if(options_len + gw_len < sizeof(options)) {
130 strcat(options, gw);
131 } else {
132 return -1;
133 }
134
135 if (!add && pd_uci_del_from_list(c, UCI_PKG_DHCP, UCI_SEC_LAN,
136 UCI_OPT_DHCP_OPT, options)) {
137 PD_ERR(pd_dhcp_add_del_gw, "pd_uci_del_from_list failed %s\n", options);
138 return 1;
139 } else if (add && pd_uci_add_list(c, UCI_PKG_DHCP, UCI_SEC_LAN,
140 UCI_OPT_DHCP_OPT, options)) {
141 PD_ERR(pd_dhcp_add_del_gw1, "pd_uci_add_list failed %s\n", options);
142 return 1;
143 }
144 return 0;
145}
146
147int pd_dhcp_add(struct pd_context *pdc, struct pd_iface *pdi)
148{
149 char *gw;
150 int dhcp_start;
151 int dhcp_third;
152 int dhcp_second;
153 char lan_alias[MAX_IP_STR_LEN];
154
155 dhcp_start = ipv4_get_last_oct(pdi->ipaddr);
156 dhcp_third = ipv4_get_third_oct(pdi->ipaddr);
157 dhcp_second = ipv4_get_second_oct(pdi->ipaddr);
158
159 if (pd.rand_gw) {
160 ipv4_get_alias(pdi->ipaddr, lan_alias);
161 gw = lan_alias;
162 } else {
163 gw = pdi->ipaddr;
164 }
165 PD_ERR(pd_dhcp_add_m0,"pd_dhcp_add: gw=%s, dhcp_start=%d\n", gw, dhcp_start);
166 if (pd_dhcp_set_limit(pdc, dhcp_second, dhcp_third, dhcp_start, 1)) {
167 PD_ERR(pd_dhcp_add, "pd_dhcp_set_limit failed start %d, limit 1\n",
168 dhcp_start);
169 return 1;
170 }
171
172 pd_fast_dhcp_reply(pdi->ipaddr);
173
174 if (pd_dhcp_add_del_gw(pdc, gw, true)) {
175 PD_ERR(pd_dhcp_add1, "pd_dhcp_add_del_gw failed %s\n", gw);
176 return 1;
177 }
178
179 if (pd_dhcp_add_del_snmask(pdc, true, dhcp_start, dhcp_third)) {
180 PD_ERR(pd_dhcp_add2, "pd_dhcp_add_del_snmask failed\n");
181 return 1;
182 }
183
184 pd_set(&pdc->status, PDC_DNSMASQ_CHANGED);
185
186 return 0;
187}
188
189int pd_dhcp_del(struct pd_context *pdc, struct pd_iface *pdi)
190{
191 char *gw;
192 char lan_alias[MAX_IP_STR_LEN];
193 int dhcp_start;
194 int dhcp_third;
195
196 dhcp_start = ipv4_get_last_oct(pdi->ipaddr);
197 dhcp_third = ipv4_get_third_oct(pdi->ipaddr);
198
199
200 if (pd.rand_gw) {
201 ipv4_get_alias(pdi->ipaddr, lan_alias);
202 gw = lan_alias;
203 } else {
204 gw = pdi->ipaddr;
205 }
206 PD_ERR(pd_dhcp_del_m0, "pd_dhcp_del: gw=%s\n", gw);
207 if (pd_dhcp_set_limit(pdc, 1, 1, UCI_DHCP_DFLT_START, UCI_DHCP_DFLT_LIMIT)) {
208 PD_ERR(pd_dhcp_del, "pd_dhcp_set_limit failed start %d, limit %d\n",
209 UCI_DHCP_DFLT_START, UCI_DHCP_DFLT_LIMIT);
210 return 1;
211 }
212
213 if (pd_dhcp_add_del_gw(pdc, gw, false)) {
214 PD_ERR(pd_dhcp_del1, "pd_dhcp_add_del_gw failed %s\n", gw);
215 return 1;
216 }
217
218 if (pd_dhcp_add_del_snmask(pdc, false, dhcp_start, dhcp_third)) {
219 PD_ERR(pd_dhcp_del2, "pd_dhcp_add_del_snmask failed\n");
220 return 1;
221 }
222
223 pd_set(&pdc->status, PDC_DNSMASQ_CHANGED);
224
225 return 0;
226}
227
228
229int pd_dhcp_change(struct pd_context *pdc, struct pd_iface *oldi,
230 struct pd_iface *newi)
231{
232 if (pd_dhcp_del(pdc, oldi)) {
233 PD_ERR(pd_dhcp_change, "pd_dhcp_del failed for %s\n", oldi->sec);
234 return 1;
235 }
236 if (pd_dhcp_add(pdc, newi)) {
237 PD_ERR(pd_dhcp_change1, "pd_dhcp_add failed for %s\n", newi->sec);
238 return 1;
239 }
240
241 return 0;
242}
243
244
245void pd_dhcp_clean(struct pd_context *pdc)
246{
247 struct uci_context *c = pdc->c;
248 char *s = pd_uci_get_opt(c, UCI_PKG_DHCP, UCI_SEC_LAN, UCI_OPT_START);
249 char *l = pd_uci_get_opt(c, UCI_PKG_DHCP, UCI_SEC_LAN, UCI_OPT_LIMIT);
250
251 if (!s || (atoi(s) != UCI_DHCP_DFLT_START) ||
252 !l || (atoi(l) != UCI_DHCP_DFLT_LIMIT))
253 goto do_clean;
254
255 return;
256
257
258do_clean:
259
260 PD_INFO(pd_dhcp_clean, "cleaning dhcp configuration\n");
261
262 if (pd_dhcp_set_limit(pdc, 1, 1, UCI_DHCP_DFLT_START, UCI_DHCP_DFLT_LIMIT)) {
263 PD_ERR(pd_dhcp_clean1, "pd_dhcp_set_limit failed\n");
264 return;
265 }
266
267 pd_uci_del(c, UCI_PKG_DHCP, UCI_SEC_LAN, UCI_OPT_DHCP_OPT, NULL);
268
269 pd_set(&pdc->status, PDC_DNSMASQ_CHANGED);
270}