Annotation of embedaddon/mpd/src/nat.c, revision 1.1.1.3
1.1 misho 1:
2: /*
3: * nat.c
4: *
5: * Written by Alexander Motin <mav@FreeBSD.org>
1.1.1.3 ! misho 6: * Rewritten by Dmitry Luhtionov <dmitryluhtionov@gmail.com>
1.1 misho 7: */
8:
9: #include "ppp.h"
10: #include "nat.h"
11: #include "iface.h"
12: #include "netgraph.h"
1.1.1.2 misho 13: #ifdef NG_NAT_DESC_LENGTH
14: #include "ngfunc.h"
15: #endif
1.1 misho 16: #include "util.h"
17:
18: /*
19: * DEFINITIONS
20: */
21:
22: /* Set menu options */
23:
24: enum {
25: SET_ADDR,
26: SET_TARGET,
27: SET_ENABLE,
28: SET_DISABLE,
29: SET_REDIRECT_PORT,
30: SET_REDIRECT_ADDR,
1.1.1.2 misho 31: SET_REDIRECT_PROTO,
32: UNSET_REDIRECT_PORT,
33: UNSET_REDIRECT_ADDR,
34: UNSET_REDIRECT_PROTO
1.1 misho 35: };
36:
37: static int NatSetCommand(Context ctx, int ac, char *av[], void *arg);
38:
39: /*
40: * GLOBAL VARIABLES
41: */
42:
1.1.1.2 misho 43: #ifdef NG_NAT_DESC_LENGTH
44: const struct cmdtab NatUnSetCmds[] = {
45: { "red-port {proto} {alias_addr} {alias_port} {local_addr} {local_port} [{remote_addr} {remote_port}]", "Redirect port",
46: NatSetCommand, AdmitBund, 2, (void *) UNSET_REDIRECT_PORT },
47: { "red-addr {alias_addr} {local_addr}", "Redirect address",
48: NatSetCommand, AdmitBund, 2, (void *) UNSET_REDIRECT_ADDR },
49: { "red-proto {proto} {alias-addr} {local_addr} [{remote-addr}]", "Redirect protocol",
50: NatSetCommand, AdmitBund, 2, (void *) UNSET_REDIRECT_PROTO },
51: { NULL },
52: };
53: #endif
54:
1.1 misho 55: const struct cmdtab NatSetCmds[] = {
56: { "address {addr}", "Set alias address",
57: NatSetCommand, AdmitBund, 2, (void *) SET_ADDR },
58: { "target {addr}", "Set target address",
59: NatSetCommand, AdmitBund, 2, (void *) SET_TARGET },
60: #ifdef NG_NAT_DESC_LENGTH
61: { "red-port {proto} {alias_addr} {alias_port} {local_addr} {local_port} [{remote_addr} {remote_port}]", "Redirect port",
62: NatSetCommand, AdmitBund, 2, (void *) SET_REDIRECT_PORT },
63: { "red-addr {alias_addr} {local_addr}", "Redirect address",
64: NatSetCommand, AdmitBund, 2, (void *) SET_REDIRECT_ADDR },
65: { "red-proto {proto} {alias-addr} {local_addr} [{remote-addr}]", "Redirect protocol",
66: NatSetCommand, AdmitBund, 2, (void *) SET_REDIRECT_PROTO },
67: #endif
68: { "enable [opt ...]", "Enable option",
69: NatSetCommand, AdmitBund, 2, (void *) SET_ENABLE },
70: { "disable [opt ...]", "Disable option",
71: NatSetCommand, AdmitBund, 2, (void *) SET_DISABLE },
72: { NULL },
73: };
74:
75: /*
76: * INTERNAL VARIABLES
77: */
78:
79: static const struct confinfo gConfList[] = {
80: { 0, NAT_CONF_LOG, "log" },
81: { 0, NAT_CONF_INCOMING, "incoming" },
82: { 0, NAT_CONF_SAME_PORTS, "same-ports" },
83: { 0, NAT_CONF_UNREG_ONLY, "unreg-only" },
84: { 0, 0, NULL },
85: };
86:
87: /*
88: * NatInit()
89: */
90:
91: void
92: NatInit(Bund b)
93: {
94: NatState const nat = &b->iface.nat;
95:
96: /* Default configuration */
97: u_addrclear(&nat->alias_addr);
98: u_addrclear(&nat->target_addr);
99: Disable(&nat->options, NAT_CONF_LOG);
100: Enable(&nat->options, NAT_CONF_INCOMING);
101: Enable(&nat->options, NAT_CONF_SAME_PORTS);
102: Disable(&nat->options, NAT_CONF_UNREG_ONLY);
103: #ifdef NG_NAT_DESC_LENGTH
104: bzero(nat->nrpt, sizeof(nat->nrpt));
105: bzero(nat->nrpt_id, sizeof(nat->nrpt_id));
106: bzero(nat->nrad, sizeof(nat->nrad));
107: bzero(nat->nrad_id, sizeof(nat->nrad_id));
108: bzero(nat->nrpr, sizeof(nat->nrpr));
109: bzero(nat->nrpr_id, sizeof(nat->nrpr_id));
110: #endif
111: }
112:
113:
114: /*
115: * NatSetCommand()
116: */
117:
118: static int
119: NatSetCommand(Context ctx, int ac, char *av[], void *arg)
120: {
121: NatState const nat = &ctx->bund->iface.nat;
1.1.1.2 misho 122: IfaceState const iface = &ctx->bund->iface;
123: #ifdef NG_NAT_DESC_LENGTH
124: char path[NG_PATHSIZ];
125: union {
126: u_char buf[sizeof(struct ng_mesg) + sizeof(uint32_t)];
127: struct ng_mesg reply;
128: } u;
129: uint32_t *const nat_id = (uint32_t *)(void *)u.reply.data;
130:
131: snprintf(path, sizeof(path), "mpd%d-%s-nat:", gPid, (char *)&ctx->bund->name);
132: #endif
1.1 misho 133:
134: if (ac == 0)
135: return(-1);
136: switch ((intptr_t)arg) {
137: case SET_TARGET:
138: #ifndef NG_NAT_LOG
139: Error("Target address setting is unsupported by current kernel");
140: #endif
141: /* FALL */
142: case SET_ADDR:
143: {
144: struct u_addr addr;
145:
146: /* Parse */
147: if (ac != 1)
148: return(-1);
149: if (!ParseAddr(av[0], &addr, ALLOW_IPV4))
150: Error("bad IP address \"%s\"", av[0]);
151:
152: /* OK */
153: if ((intptr_t)arg == SET_ADDR) {
154: nat->alias_addr = addr;
155: } else {
156: nat->target_addr = addr;
157: }
158: }
159: break;
160:
161: #ifdef NG_NAT_DESC_LENGTH
162: case SET_REDIRECT_PORT:
1.1.1.2 misho 163: case UNSET_REDIRECT_PORT:
1.1 misho 164: {
165: struct protoent *proto;
166: struct in_addr l_addr, a_addr, r_addr;
1.1.1.2 misho 167: int lp, ap, rp = 0;
168: uint32_t k;
1.1 misho 169:
170: /* Parse */
171: if (ac != 5 && ac != 7)
172: return(-1);
173: if ((proto = getprotobyname(av[0])) == 0)
174: Error("bad PROTO name \"%s\"", av[0]);
175: if (!inet_aton (av[1], &a_addr))
176: Error("bad alias IP address \"%s\"", av[1]);
177: ap = atoi(av[2]);
178: if (ap <= 0 || ap > 65535)
179: Error("Incorrect alias port number \"%s\"", av[2]);
180: if (!inet_aton (av[3], &l_addr))
181: Error("bad local IP address \"%s\"", av[3]);
182: lp = atoi(av[4]);
183: if (lp <= 0 || lp > 65535)
184: Error("Incorrect local port number \"%s\"", av[4]);
185: if (ac == 7) {
186: if (!inet_aton (av[5], &r_addr))
187: Error("bad remote IP address \"%s\"", av[5]);
188: rp = atoi(av[6]);
189: if (rp <= 0 || rp > 65535)
190: Error("Incorrect remote port number \"%s\"", av[6]);
191: }
192: /* OK */
1.1.1.2 misho 193: if ((intptr_t)arg == SET_REDIRECT_PORT) {
194: for (k=0;k<NM_PORT;k++) {
195: if (nat->nrpt_id[k] == 0) {
196: memcpy(&nat->nrpt[k].local_addr, &l_addr, sizeof(struct in_addr));
197: memcpy(&nat->nrpt[k].alias_addr, &a_addr, sizeof(struct in_addr));
198: nat->nrpt[k].local_port = lp;
199: nat->nrpt[k].alias_port = ap;
200: if (ac == 7) {
201: memcpy(&nat->nrpt[k].remote_addr, &r_addr, sizeof(struct in_addr));
202: nat->nrpt[k].remote_port = rp;
203: }
204: nat->nrpt[k].proto = (uint8_t)proto->p_proto;
205: snprintf(nat->nrpt[k].description, NG_NAT_DESC_LENGTH, "nat-port-%d", k);
206: nat->nrpt_id[k] = -1;
207: if (iface->up && iface->nat_up) {
208: if (NgFuncSendQuery(path, NGM_NAT_COOKIE, NGM_NAT_REDIRECT_PORT,
209: &nat->nrpt[k], sizeof(struct ng_nat_redirect_port),
210: &u.reply, sizeof(u), NULL) == 0)
211: nat->nrpt_id[k] = *nat_id;
212: }
213: break;
1.1 misho 214: }
215: }
1.1.1.2 misho 216: if (k == NM_PORT)
217: Error("max number of redirect-port \"%d\" reached", NM_PORT);
218: } else {
219: struct ng_nat_redirect_port tmp_rule;
220:
221: bzero(&tmp_rule, sizeof(struct ng_nat_redirect_port));
222: memcpy(&tmp_rule.local_addr, &l_addr, sizeof(struct in_addr));
223: memcpy(&tmp_rule.alias_addr, &a_addr, sizeof(struct in_addr));
224: tmp_rule.local_port = lp;
225: tmp_rule.alias_port = ap;
226: if (ac == 7) {
227: memcpy(&tmp_rule.remote_addr, &r_addr, sizeof(struct in_addr));
228: tmp_rule.remote_port = rp;
229: }
230: tmp_rule.proto = (uint8_t)proto->p_proto;
231: /* hack to fill misaligned space */
232: snprintf(tmp_rule.description, NG_NAT_DESC_LENGTH, "nat-port-0");
233: for (k=0;k<NM_PORT;k++) {
234: if ((nat->nrpt_id[k] != 0) && (memcmp(&tmp_rule, &nat->nrpt[k],
235: sizeof(struct ng_nat_redirect_port)-NG_NAT_DESC_LENGTH) == 0)) {
236: if (iface->up && iface->nat_up) {
237: if (NgSendMsg(gLinksCsock, path, NGM_NAT_COOKIE,
238: NGM_NAT_REDIRECT_DELETE, &k, sizeof(k)) < 0) {
239: Perror("Can't delete nat rule");
240: break;
241: }
242: }
243: nat->nrpt_id[k] = 0;
244: bzero(&nat->nrpt[k], sizeof(struct ng_nat_redirect_port));
245: break;
246: }
247: }
248: if (k == NM_PORT)
249: Error("Rule not found");
1.1 misho 250: }
251: }
252: break;
253:
254: case SET_REDIRECT_ADDR:
1.1.1.2 misho 255: case UNSET_REDIRECT_ADDR:
1.1 misho 256: {
257: struct in_addr l_addr, a_addr;
1.1.1.2 misho 258: uint32_t k;
1.1 misho 259:
260: /* Parse */
261: if (ac != 2)
262: return(-1);
263: if (!inet_aton (av[0], &a_addr))
264: Error("bad alias IP address \"%s\"", av[0]);
265: if (!inet_aton (av[1], &l_addr))
266: Error("bad local IP address \"%s\"", av[1]);
267:
268: /* OK */
1.1.1.2 misho 269: if ((intptr_t)arg == SET_REDIRECT_ADDR) {
270: for (k=0;k<NM_ADDR;k++) {
271: if (nat->nrad_id[k] == 0) {
272: memcpy(&nat->nrad[k].local_addr, &l_addr, sizeof(struct in_addr));
273: memcpy(&nat->nrad[k].alias_addr, &a_addr, sizeof(struct in_addr));
274: snprintf(nat->nrad[k].description, NG_NAT_DESC_LENGTH, "nat-addr-%d", k);
275: nat->nrad_id[k] = -1;
276: if (iface->up && iface->nat_up) {
277: if (NgFuncSendQuery(path, NGM_NAT_COOKIE, NGM_NAT_REDIRECT_ADDR,
278: &nat->nrad[k], sizeof(struct ng_nat_redirect_addr),
279: &u.reply, sizeof(u), NULL) == 0)
280: nat->nrad_id[k] = *nat_id;
281: }
282: break;
283: }
284: }
285: if (k == NM_ADDR)
286: Error("max number of redirect-addr \"%d\" reached", NM_ADDR);
287: } else {
288: struct ng_nat_redirect_addr tmp_rule;
289:
290: bzero(&tmp_rule, sizeof(struct ng_nat_redirect_addr));
291: memcpy(&tmp_rule.local_addr, &l_addr, sizeof(struct in_addr));
292: memcpy(&tmp_rule.alias_addr, &a_addr, sizeof(struct in_addr));
293: /* hack to fill misaligned space */
294: snprintf(tmp_rule.description, NG_NAT_DESC_LENGTH, "nat-addr-0");
295: for (k=0;k<NM_ADDR;k++) {
296: if ((nat->nrad_id[k] != 0) && (memcmp(&tmp_rule, &nat->nrad[k],
297: sizeof(struct ng_nat_redirect_addr)-NG_NAT_DESC_LENGTH) == 0)) {
298: if (iface->up && iface->nat_up) {
299: if (NgSendMsg(gLinksCsock, path, NGM_NAT_COOKIE,
300: NGM_NAT_REDIRECT_DELETE, &k, sizeof(k)) < 0) {
301: Perror("Can't delete nat rule");
302: break;
303: }
304: }
305: nat->nrad_id[k] = 0;
306: bzero(&nat->nrad[k], sizeof(struct ng_nat_redirect_addr));
307: break;
308: }
1.1 misho 309: }
1.1.1.2 misho 310: if (k == NM_ADDR)
311: Error("Rule not found");
1.1 misho 312: }
313: }
314: break;
315:
316: case SET_REDIRECT_PROTO:
1.1.1.2 misho 317: case UNSET_REDIRECT_PROTO:
1.1 misho 318: {
319: struct protoent *proto;
320: struct in_addr l_addr, a_addr, r_addr;
1.1.1.2 misho 321: uint32_t k;
1.1 misho 322:
323: /* Parse */
324: if (ac != 3 && ac != 4)
325: return(-1);
326: if ((proto = getprotobyname(av[0])) == 0)
327: Error("bad PROTO name \"%s\"", av[0]);
328: if (!inet_aton (av[1], &a_addr))
329: Error("bad alias IP address \"%s\"", av[1]);
330: if (!inet_aton (av[2], &l_addr))
331: Error("bad local IP address \"%s\"", av[2]);
332: if (ac == 4) {
333: if (!inet_aton (av[3], &r_addr))
334: Error("bad remote IP address \"%s\"", av[3]);
335: }
336:
337: /* OK */
1.1.1.2 misho 338: if ((intptr_t)arg == SET_REDIRECT_PROTO) {
339: for (k=0;k<NM_PROTO;k++) {
340: if (nat->nrpr_id[k] == 0) {
341: memcpy(&nat->nrpr[k].local_addr, &l_addr, sizeof(struct in_addr));
342: memcpy(&nat->nrpr[k].alias_addr, &a_addr, sizeof(struct in_addr));
343: if (ac == 4)
344: memcpy(&nat->nrpr[k].remote_addr, &r_addr, sizeof(struct in_addr));
345: nat->nrpr[k].proto = (uint8_t)proto->p_proto;
346: snprintf(nat->nrpr[k].description, NG_NAT_DESC_LENGTH, "nat-proto-%d", k);
347: nat->nrpr_id[k] = -1;
348: if (iface->up && iface->nat_up) {
349: if (NgFuncSendQuery(path, NGM_NAT_COOKIE, NGM_NAT_REDIRECT_PROTO,
350: &nat->nrpr[k], sizeof(struct ng_nat_redirect_proto),
351: &u.reply, sizeof(u), NULL) == 0)
352: nat->nrpr_id[k] = *nat_id;
353: }
354: break;
355: }
1.1 misho 356: }
1.1.1.2 misho 357: if (k == NM_PROTO)
358: Error("max number of redirect-proto \"%d\" reached", NM_PROTO);
359: } else {
360: struct ng_nat_redirect_proto tmp_rule;
361:
362: bzero(&tmp_rule, sizeof(struct ng_nat_redirect_proto));
363: memcpy(&tmp_rule.local_addr, &l_addr, sizeof(struct in_addr));
364: memcpy(&tmp_rule.alias_addr, &a_addr, sizeof(struct in_addr));
365: if (ac == 4) {
366: memcpy(&tmp_rule.remote_addr, &r_addr, sizeof(struct in_addr));
367: }
368: tmp_rule.proto = (uint8_t)proto->p_proto;
369: /* hack to fill misaligned space */
370: snprintf(tmp_rule.description, NG_NAT_DESC_LENGTH, "nat-proto-0");
371: for (k=0;k<NM_PROTO;k++) {
372: if ((nat->nrpr_id[k] != 0) && (memcmp(&tmp_rule, &nat->nrpr[k],
373: sizeof(struct ng_nat_redirect_proto)-NG_NAT_DESC_LENGTH) == 0)) {
374: if (iface->up && iface->nat_up) {
375: if (NgSendMsg(gLinksCsock, path, NGM_NAT_COOKIE,
376: NGM_NAT_REDIRECT_DELETE, &k, sizeof(k)) < 0) {
377: Perror("Can't delete nat rule");
378: break;
379: }
380: }
381: nat->nrpr_id[k] = 0;
382: bzero(&nat->nrpr[k], sizeof(struct ng_nat_redirect_proto));
383: break;
384: }
385: }
386: if (k == NM_PROTO)
387: Error("Rule not found");
1.1 misho 388: }
389: }
390: break;
391: #endif
392:
393: case SET_ENABLE:
394: EnableCommand(ac, av, &nat->options, gConfList);
395: break;
396:
397: case SET_DISABLE:
398: DisableCommand(ac, av, &nat->options, gConfList);
399: break;
400:
401: default:
402: assert(0);
403: }
404: return(0);
405: }
406:
407: /*
408: * NatStat()
409: */
410:
411: int
412: NatStat(Context ctx, int ac, char *av[], void *arg)
413: {
414: NatState const nat = &ctx->bund->iface.nat;
1.1.1.3 ! misho 415: #ifdef NG_NAT_LIBALIAS_INFO
1.1.1.2 misho 416: IfaceState const iface = &ctx->bund->iface;
417: union {
418: u_char buf[sizeof(struct ng_mesg) + sizeof(struct ng_nat_libalias_info)];
419: struct ng_mesg reply;
420: } u;
421: struct ng_nat_libalias_info *const li = \
422: (struct ng_nat_libalias_info *)(void *)u.reply.data;
423: char path[NG_PATHSIZ];
424: #endif
1.1 misho 425: char buf[48];
426: int k;
427:
428: Printf("NAT configuration:\r\n");
429: Printf("\tAlias addresses : %s\r\n",
430: u_addrtoa(&nat->alias_addr,buf,sizeof(buf)));
431: Printf("\tTarget addresses: %s\r\n",
432: u_addrtoa(&nat->target_addr,buf,sizeof(buf)));
433: #ifdef NG_NAT_DESC_LENGTH
434: Printf("Redirect ports:\r\n");
435: for (k=0;k<NM_PORT;k++) {
1.1.1.2 misho 436: if (nat->nrpt_id[k] != 0) {
1.1 misho 437: struct protoent *proto;
1.1.1.2 misho 438: char li[16], ai[16], ri[16];
1.1 misho 439: inet_ntop(AF_INET, &nat->nrpt[k].local_addr, li, sizeof(li));
440: inet_ntop(AF_INET, &nat->nrpt[k].alias_addr, ai, sizeof(ai));
441: inet_ntop(AF_INET, &nat->nrpt[k].remote_addr, ri, sizeof(ri));
442: proto = getprotobynumber(nat->nrpt[k].proto);
1.1.1.2 misho 443: Printf("\t%s %s:%d %s:%d %s:%d (%sactive)\r\n", proto->p_name,
1.1 misho 444: ai, nat->nrpt[k].alias_port, li, nat->nrpt[k].local_port,
1.1.1.2 misho 445: ri, nat->nrpt[k].remote_port, nat->nrpt_id[k]<0?"in":"");
1.1 misho 446: }
447: }
448: Printf("Redirect address:\r\n");
449: for (k=0;k<NM_ADDR;k++) {
1.1.1.2 misho 450: if (nat->nrad_id[k] != 0) {
451: char li[16], ai[16];
1.1 misho 452: inet_ntop(AF_INET, &nat->nrad[k].local_addr, li, sizeof(li));
453: inet_ntop(AF_INET, &nat->nrad[k].alias_addr, ai, sizeof(ai));
1.1.1.2 misho 454: Printf("\t%s %s (%sactive)\r\n", ai, li, nat->nrad_id[k]<0?"in":"");
1.1 misho 455: }
456: }
457: Printf("Redirect proto:\r\n");
458: for (k=0;k<NM_PROTO;k++) {
1.1.1.2 misho 459: if (nat->nrpr_id[k] != 0) {
1.1 misho 460: struct protoent *proto;
1.1.1.2 misho 461: char li[16], ai[16], ri[16];
1.1 misho 462: proto = getprotobynumber(nat->nrpr[k].proto);
463: inet_ntop(AF_INET, &nat->nrpr[k].local_addr, li, sizeof(li));
464: inet_ntop(AF_INET, &nat->nrpr[k].alias_addr, ai, sizeof(ai));
465: inet_ntop(AF_INET, &nat->nrpr[k].remote_addr, ri, sizeof(ri));
1.1.1.2 misho 466: Printf("\t%s %s %s %s (%sactive)\r\n", proto->p_name,
467: ai, li, ri, nat->nrpr_id[k]<0?"in":"");
1.1 misho 468: }
469: }
470: #endif
471: Printf("NAT options:\r\n");
472: OptStat(ctx, &nat->options, gConfList);
1.1.1.3 ! misho 473: #ifdef NG_NAT_LIBALIAS_INFO
1.1.1.2 misho 474: if (Enabled(&nat->options, NAT_CONF_LOG) && iface->up && iface->nat_up) {
475: snprintf(path, sizeof(path), "mpd%d-%s-nat:", gPid, \
476: (char *)&ctx->bund->name);
1.1.1.3 ! misho 477: bzero(li, sizeof(struct ng_nat_libalias_info));
1.1.1.2 misho 478: Printf("LibAlias statistic:\r\n");
479: if (NgFuncSendQuery(path, NGM_NAT_COOKIE, NGM_NAT_LIBALIAS_INFO,
480: NULL, 0, &u.reply, sizeof(u), NULL) < 0)
481: Perror("Can't get LibAlis stats");
482: Printf("\ticmpLinkCount : %u\r\n", li->icmpLinkCount);
483: Printf("\tudpLinkCount : %u\r\n", li->udpLinkCount);
484: Printf("\ttcpLinkCount : %u\r\n", li->tcpLinkCount);
485: Printf("\tsctpLinkCount : %u\r\n", li->sctpLinkCount);
486: Printf("\tpptpLinkCount : %u\r\n", li->pptpLinkCount);
487: Printf("\tprotoLinkCount : %u\r\n", li->protoLinkCount);
488: Printf("\tfragmentIdLinkCount : %u\r\n", li->fragmentIdLinkCount);
489: Printf("\tfragmentPtrLinkCount : %u\r\n", li->fragmentPtrLinkCount);
490: Printf("\tsockCount : %u\r\n", li->sockCount);
491: }
492: #endif
1.1 misho 493: return(0);
494: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>