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