1 /* l2tpns plugin control */
10 #include <sys/socket.h>
11 #include <linux/rtnetlink.h>
22 { "load_plugin", " PLUGIN Load named plugin", NSCTL_REQ_LOAD
},
23 { "unload_plugin", " PLUGIN Unload named plugin", NSCTL_REQ_UNLOAD
},
24 { "help", " List available commands", NSCTL_REQ_HELP
},
29 static int timeout
= 2; // 2 seconds
32 #define USAGE() fprintf(stderr, "Usage: %s [-d] [-h HOST[:PORT]] [-t TIMEOUT] COMMAND [ARG ...]\n", me)
34 static struct nsctl
*request(char *host
, int port
, int type
, int argc
, char *argv
[]);
36 int main(int argc
, char *argv
[])
45 if ((p
= strrchr((me
= argv
[0]), '/')))
49 while ((i
= getopt(argc
, argv
, "dh:t:")) != -1)
61 timeout
= atoi(optarg
);
72 if (argc
< 1 || !argv
[0][0])
81 if ((p
= strchr(host
, ':')))
86 fprintf(stderr
, "%s: invalid port `%s'\n", me
, p
+ 1);
97 for (i
= 0; !req_type
&& builtins
[i
].command
; i
++)
98 if (!strcmp(argv
[0], builtins
[i
].command
))
99 req_type
= builtins
[i
].action
;
101 if (req_type
== NSCTL_REQ_HELP
)
103 printf("Available commands:\n");
104 for (i
= 0; builtins
[i
].command
; i
++)
105 printf(" %s%s\n", builtins
[i
].command
, builtins
[i
].usage
);
115 req_type
= NSCTL_REQ_CONTROL
;
118 if ((res
= request(host
, port
, req_type
, argc
, argv
)))
120 FILE *stream
= stderr
;
121 int status
= EXIT_FAILURE
;
123 if (res
->type
== NSCTL_RES_OK
)
126 status
= EXIT_SUCCESS
;
129 for (i
= 0; i
< res
->argc
; i
++)
130 fprintf(stream
, "%s\n", res
->argv
[i
]);
138 static void sigalrm_handler(int sig
) { }
140 static struct nsctl
*request(char *host
, int port
, int type
, int argc
, char *argv
[])
142 static struct nsctl res
;
143 struct sockaddr_in peer
;
144 socklen_t len
= sizeof(peer
);
145 struct hostent
*h
= gethostbyname(host
);
147 uint8_t buf
[NSCTL_MAX_PKT_SZ
];
151 if (!h
|| h
->h_addrtype
!= AF_INET
)
153 fprintf(stderr
, "%s: invalid host `%s'\n", me
, host
);
157 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0)
159 fprintf(stderr
, "%s: can't create udp socket (%s)\n", me
, strerror(errno
));
163 memset(&peer
, 0, len
);
164 peer
.sin_family
= AF_INET
;
165 peer
.sin_port
= htons(port
);
166 memcpy(&peer
.sin_addr
.s_addr
, h
->h_addr
, sizeof(peer
.sin_addr
.s_addr
));
168 if (connect(fd
, (struct sockaddr
*) &peer
, sizeof(peer
)) < 0)
170 fprintf(stderr
, "%s: udp connect failed (%s)\n", me
, strerror(errno
));
174 if ((sz
= pack_control(buf
, sizeof(buf
), type
, argc
, argv
)) < 0)
176 fprintf(stderr
, "%s: error packing request\n", me
);
183 if (unpack_control(&req
, buf
, sz
) == type
)
185 fprintf(stderr
, "Sending ");
186 dump_control(&req
, stderr
);
190 if (send(fd
, buf
, sz
, 0) < 0)
192 fprintf(stderr
, "%s: error sending request (%s)\n", me
, strerror(errno
));
199 struct sigaction alrm
;
200 alrm
.sa_handler
= sigalrm_handler
;
201 sigemptyset(&alrm
.sa_mask
);
204 sigaction(SIGALRM
, &alrm
, 0);
208 sz
= recv(fd
, buf
, sizeof(buf
), 0);
213 fprintf(stderr
, "%s: error receiving response (%s)\n", me
,
214 errno
== EINTR
? "timed out" : strerror(errno
));
219 if ((type
= unpack_control(&res
, buf
, sz
)) > 0 && type
& NSCTL_RESPONSE
)
223 fprintf(stderr
, "Received ");
224 dump_control(&res
, stderr
);
230 err
= "unknown error";
233 case NSCTL_ERR_SHORT
: err
= "short packet"; break;
234 case NSCTL_ERR_LONG
: err
= "extra data"; break;
235 case NSCTL_ERR_MAGIC
: err
= "bad magic"; break;
236 case NSCTL_ERR_TYPE
: err
= "invalid type"; break;
239 fprintf(stderr
, "%s: %s\n", me
, err
);