1 /* l2tpns plugin control */
10 #include <sys/socket.h>
11 #include <linux/rtnetlink.h>
21 { "load_plugin", " PLUGIN Load named plugin", NSCTL_REQ_LOAD
},
22 { "unload_plugin", " PLUGIN Unload named plugin", NSCTL_REQ_UNLOAD
},
23 { "help", " List available commands", NSCTL_REQ_HELP
},
28 static int timeout
= 2; // 2 seconds
31 #define USAGE() fprintf(stderr, "Usage: %s [-d] [-h HOST[:PORT]] [-t TIMEOUT] COMMAND [ARG ...]\n", me)
33 static struct nsctl
*request(char *host
, int port
, int type
, int argc
, char *argv
[]);
35 int main(int argc
, char *argv
[])
44 if ((p
= strrchr((me
= argv
[0]), '/')))
48 while ((i
= getopt(argc
, argv
, "dh:t:")) != -1)
60 timeout
= atoi(optarg
);
71 if (argc
< 1 || !argv
[0][0])
80 if ((p
= strchr(host
, ':')))
85 fprintf(stderr
, "%s: invalid port `%s'\n", me
, p
+ 1);
96 for (i
= 0; !req_type
&& builtins
[i
].command
; i
++)
97 if (!strcmp(argv
[0], builtins
[i
].command
))
98 req_type
= builtins
[i
].action
;
100 if (req_type
== NSCTL_REQ_HELP
)
102 printf("Available commands:\n");
103 for (i
= 0; builtins
[i
].command
; i
++)
104 printf(" %s%s\n", builtins
[i
].command
, builtins
[i
].usage
);
114 req_type
= NSCTL_REQ_CONTROL
;
117 if ((res
= request(host
, port
, req_type
, argc
, argv
)))
119 FILE *stream
= stderr
;
120 int status
= EXIT_FAILURE
;
122 if (res
->type
== NSCTL_RES_OK
)
125 status
= EXIT_SUCCESS
;
128 for (i
= 0; i
< res
->argc
; i
++)
129 fprintf(stream
, "%s\n", res
->argv
[i
]);
137 static void sigalrm_handler(int sig
) { }
139 static struct nsctl
*request(char *host
, int port
, int type
, int argc
, char *argv
[])
141 static struct nsctl res
;
142 struct sockaddr_in peer
;
143 socklen_t len
= sizeof(peer
);
144 struct hostent
*h
= gethostbyname(host
);
146 uint8_t buf
[NSCTL_MAX_PKT_SZ
];
150 if (!h
|| h
->h_addrtype
!= AF_INET
)
152 fprintf(stderr
, "%s: invalid host `%s'\n", me
, host
);
156 if ((fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0)
158 fprintf(stderr
, "%s: can't create udp socket (%s)\n", me
, strerror(errno
));
162 memset(&peer
, 0, len
);
163 peer
.sin_family
= AF_INET
;
164 peer
.sin_port
= htons(port
);
165 memcpy(&peer
.sin_addr
.s_addr
, h
->h_addr
, sizeof(peer
.sin_addr
.s_addr
));
167 if (connect(fd
, (struct sockaddr
*) &peer
, sizeof(peer
)) < 0)
169 fprintf(stderr
, "%s: udp connect failed (%s)\n", me
, strerror(errno
));
173 if ((sz
= pack_control(buf
, sizeof(buf
), type
, argc
, argv
)) < 0)
175 fprintf(stderr
, "%s: error packing request\n", me
);
182 if (unpack_control(&req
, buf
, sz
) == type
)
184 fprintf(stderr
, "Sending ");
185 dump_control(&req
, stderr
);
189 if (send(fd
, buf
, sz
, 0) < 0)
191 fprintf(stderr
, "%s: error sending request (%s)\n", me
, strerror(errno
));
198 struct sigaction alrm
;
199 alrm
.sa_handler
= sigalrm_handler
;
200 sigemptyset(&alrm
.sa_mask
);
203 sigaction(SIGALRM
, &alrm
, 0);
207 sz
= recv(fd
, buf
, sizeof(buf
), 0);
212 fprintf(stderr
, "%s: error receiving response (%s)\n", me
,
213 errno
== EINTR
? "timed out" : strerror(errno
));
218 if ((type
= unpack_control(&res
, buf
, sz
)) > 0 && type
& NSCTL_RESPONSE
)
222 fprintf(stderr
, "Received ");
223 dump_control(&res
, stderr
);
229 err
= "unknown error";
232 case NSCTL_ERR_SHORT
: err
= "short packet"; break;
233 case NSCTL_ERR_LONG
: err
= "extra data"; break;
234 case NSCTL_ERR_MAGIC
: err
= "bad magic"; break;
235 case NSCTL_ERR_TYPE
: err
= "invalid type"; break;
238 fprintf(stderr
, "%s: %s\n", me
, err
);