154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley/* dhcp6.c - DHCP6 client for dynamic network configuration.
254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley *
354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley * Copyright 2015 Rajni Kant <rajnikant12345@gmail.com>
454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley *
554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley * Not in SUSv4.
654a13f9ef4380501d3b12bb1f04408f5607d46eeRob LandleyUSE_DHCP6(NEWTOY(dhcp6, "r:A#<0T#<0t#<0s:p:i:SRvqnbf", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleyconfig DHCP6
954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  bool "dhcp6"
1054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  default n
1154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  help
1254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  usage: dhcp6 [-fbnqvR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]
1354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
1454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        Configure network dynamicaly using DHCP.
1554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
1654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -i Interface to use (default eth0)
1754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -p Create pidfile
1854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -s Run PROG at DHCP events
1954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -t Send up to N Solicit packets
2054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -T Pause between packets (default 3 seconds)
2154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -A Wait N seconds after failure (default 20)
2254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -f Run in foreground
2354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -b Background if lease is not obtained
2454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -n Exit if lease is not obtained
2554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -q Exit after obtaining lease
2654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -R Release IP on exit
2754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -S Log to syslog too
2854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -r Request this IP address
2954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      -v Verbose
3054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
3154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      Signals:
3254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      USR1  Renew current lease
3354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      USR2  Release current lease
3454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley*/
3554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define FOR_dhcp6
3654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#include "toys.h"
3754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#include <linux/sockios.h>
3854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#include <linux/if_ether.h>
3954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#include <netinet/ip.h>
4054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#include <netinet/ip6.h>
4154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#include <netinet/udp.h>
4254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#include <linux/if_packet.h>
4354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#include <syslog.h>
4454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
4554a13f9ef4380501d3b12bb1f04408f5607d46eeRob LandleyGLOBALS(
4654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  char *interface_name, *pidfile, *script;
4754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  long retry, timeout, errortimeout;
4854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  char *req_ip;
4954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  int length, state, request_length, sock, sock1, status, retval, retries;
5054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  struct timeval tv;
5154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t transction_id[3];
5254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  struct sockaddr_in6 input_socket6;
5354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley)
5454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
5554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6SOLICIT        1
5654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6ADVERTISE      2   // server -> client
5754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6REQUEST        3
5854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6CONFIRM        4
5954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6RENEW          5
6054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6REBIND         6
6154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6REPLY          7   // server -> client
6254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6RELEASE        8
6354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6DECLINE        9
6454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6RECONFIGURE    10  // server -> client
6554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6INFOREQUEST    11
6654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6RELAYFLOW      12  // relay -> relay/server
6754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6RELAYREPLY     13  // server/relay -> relay
6854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
6954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley// DHCPv6 option codes (partial). See RFC 3315
7054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_CLIENTID      1
7154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_SERVERID      2
7254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_IA_NA         3
7354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_IA_ADDR       5
7454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_ORO           6
7554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_PREFERENCE    7
7654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_ELAPSED_TIME  8
7754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_RELAY_MSG     9
7854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_STATUS_CODE   13
7954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_IA_PD         25
8054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_OPT_IA_PREFIX     26
8154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
8254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_STATUS_SUCCESS        0
8354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_STATUS_NOADDRSAVAIL   2
8454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
8554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_DUID_LLT    1
8654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_DUID_EN     2
8754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_DUID_LL     3
8854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCP6_DUID_UUID   4
8954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
9054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCPC_SERVER_PORT     547
9154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define DHCPC_CLIENT_PORT     546
9254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
9354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define LOG_SILENT          0x0
9454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define LOG_CONSOLE         0x1
9554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley#define LOG_SYSTEM          0x2
9654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
9754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleytypedef struct __attribute__((packed)) dhcp6_msg_s {
9854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t msgtype, transaction_id[3], options[524];
9954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley} dhcp6_msg_t;
10054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
10154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleytypedef struct __attribute__((packed)) optval_duid_llt {
10254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint16_t type;
10354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint16_t hwtype;
10454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint32_t time;
10554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t lladdr[6];
10654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley} DUID;
10754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
10854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleytypedef struct __attribute__((packed)) optval_ia_na {
10954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint32_t iaid, t1, t2;
11054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley} IA_NA;
11154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
11254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleytypedef struct __attribute__((packed)) dhcp6_raw_s {
11354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  struct ip6_hdr iph;
11454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  struct udphdr udph;
11554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dhcp6_msg_t dhcp6;
11654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley} dhcp6_raw_t;
11754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
11854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleytypedef struct __attribute__((packed)) dhcp_data_client {
11954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint16_t  status_code;
12054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint32_t iaid , t1,t2, pf_lf, va_lf;
12154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t ipaddr[17] ;
12254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley} DHCP_DATA;
12354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
12454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic DHCP_DATA dhcp_data;
12554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic dhcp6_raw_t *mymsg;
12654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic dhcp6_msg_t mesg;
12754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic DUID *duid;
12854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
12954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void (*dbg)(char *format, ...);
13054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void dummy(char *format, ...)
13154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
13254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  return;
13354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
13454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
13554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void logit(char *format, ...)
13654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
13754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  int used;
13854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  char *msg;
13954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  va_list p, t;
14054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t infomode = LOG_SILENT;
14154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
142547c9167565cf8a2bba8bd79850889101866814aRob Landley  if (toys.optflags & FLAG_S) infomode |= LOG_SYSTEM;
143547c9167565cf8a2bba8bd79850889101866814aRob Landley  if(toys.optflags & FLAG_v) infomode |= LOG_CONSOLE;
14454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  va_start(p, format);
14554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  va_copy(t, p);
14654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  used = vsnprintf(NULL, 0, format, t);
14754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  used++;
14854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  va_end(t);
14954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
15054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  msg = xmalloc(used);
15154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  vsnprintf(msg, used, format, p);
15254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  va_end(p);
15354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
15454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (infomode & LOG_SYSTEM) syslog(LOG_INFO, "%s", msg);
15554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (infomode & LOG_CONSOLE) printf("%s", msg);
15654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  free(msg);
15754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  return;
15854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
15954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
16054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void get_mac(uint8_t *mac, char *interface)
16154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
16254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  int fd;
16354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  struct ifreq req;
16454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
16554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (!mac) return;
16654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  fd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
16754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  req.ifr_addr.sa_family = AF_INET6;
16854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  xstrncpy(req.ifr_name, interface, IFNAMSIZ);
16954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  xioctl(fd, SIOCGIFHWADDR, &req);
17054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  memcpy(mac, req.ifr_hwaddr.sa_data, 6);
17154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  xclose(fd);
17254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
17354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
17454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void fill_option(uint16_t option_id, uint16_t option_len, uint8_t **dhmesg)
17554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
17654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t *tmp = *dhmesg;
17754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
17854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  *((uint16_t*)tmp) = htons(option_id);
17954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  *(uint16_t*)(tmp+2) = htons(option_len);
18054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  *dhmesg += 4;
18154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  TT.length += 4;
18254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
18354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
18454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void fill_clientID()
18554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
18654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t *tmp = &mesg.options[TT.length];
18754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
18854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if(!duid) {
18954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    uint8_t mac[7] = {0,};
19054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    duid = (DUID*)malloc(sizeof(DUID));
19154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    duid->type = htons(1);
19254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    duid->hwtype = htons(1);
19354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    duid->time = htonl((uint32_t)(time(NULL) - 946684800) & 0xffffffff);
19454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    fill_option(DHCP6_OPT_CLIENTID,14,&tmp);
19554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    get_mac(mac, TT.interface_name);
19654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    memcpy(duid->lladdr,mac, 6);
19754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    memcpy(tmp,(uint8_t*)duid,sizeof(DUID));
19854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
19954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  else {
20054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    fill_option(DHCP6_OPT_CLIENTID,14,&tmp);
20154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    memcpy(tmp,(uint8_t*)duid,sizeof(DUID));
20254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
20354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  TT.length += sizeof(DUID);
20454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
20554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
20654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley// TODO: make it generic for multiple options.
20754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void fill_optionRequest()
20854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
20954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t *tmp = &mesg.options[TT.length];
21054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
21154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  fill_option(DHCP6_OPT_ORO,4,&tmp);
21254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  *(uint16_t*)(tmp+4) = htons(23);
21354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  *(uint16_t*)(tmp+6) = htons(24);
21454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  TT.length += 4;
21554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
21654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
21754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void fill_elapsedTime()
21854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
21954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t *tmp = &mesg.options[TT.length];
22054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
22154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  fill_option(DHCP6_OPT_ELAPSED_TIME, 2, &tmp);
22254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  *(uint16_t*)(tmp+6) = htons(0);
22354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  TT.length += 2;
22454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
22554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
22654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void fill_iaid()
22754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
22854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  IA_NA iana;
22954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t *tmp = &mesg.options[TT.length];
23054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
23154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  fill_option(DHCP6_OPT_IA_NA, 12, &tmp);
23254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  iana.iaid = rand();
23354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  iana.t1 = 0xffffffff;
23454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  iana.t2 = 0xffffffff;
23554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  memcpy(tmp, (uint8_t*)&iana, sizeof(IA_NA));
23654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  TT.length += sizeof(IA_NA);
23754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
23854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
23954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley//static void mode_raw(int *sock_t)
24054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void mode_raw()
24154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
24254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  int constone = 1;
24354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  struct sockaddr_ll sockll;
24454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
24554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (TT.sock > 0) xclose(TT.sock);
24654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  TT.sock = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
24754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
24854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  memset(&sockll, 0, sizeof(sockll));
24954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  sockll.sll_family = AF_PACKET;
25054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  sockll.sll_protocol = htons(ETH_P_IPV6);
25154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  sockll.sll_ifindex = if_nametoindex(TT.interface_name);
25254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (bind(TT.sock, (struct sockaddr *) &sockll, sizeof(sockll))) {
25354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    xclose(TT.sock);
25454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    error_exit("MODE RAW : Bind fail.\n");
25554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
25654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (setsockopt(TT.sock, SOL_PACKET, PACKET_HOST,&constone, sizeof(int)) < 0) {
25754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley		if (errno != ENOPROTOOPT) error_exit("MODE RAW : Bind fail.\n");
25854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley	}
25954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
26054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
26154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void generate_transection_id()
26254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
26354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  int i, r = rand() % 0xffffff;
26454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
26554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  for (i=0; i<3; i++) {
26654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    TT.transction_id[i] = r%0xff;
26754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    r = r/10;
26854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
26954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
27054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
27154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void set_timeout(int seconds)
27254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
27354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  TT.tv.tv_sec = seconds;
27454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  TT.tv.tv_usec = 100000;
27554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
27654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
27754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void  send_msg(int type)
27854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
27954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  struct sockaddr_in6 addr6;
28054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  int sendlength = 0;
28154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
28254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  memset(&addr6, 0, sizeof(addr6));
28354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  addr6.sin6_family = AF_INET6;
28454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  addr6.sin6_port = htons(DHCPC_SERVER_PORT); //SERVER_PORT
28554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  inet_pton(AF_INET6, "ff02::1:2", &addr6.sin6_addr);
28654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  mesg.msgtype = type;
28754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  generate_transection_id();
28854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  memcpy(mesg.transaction_id, TT.transction_id, 3);
28954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
29054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (type  == DHCP6SOLICIT) {
29154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    TT.length = 0;
29254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    fill_clientID();
29354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    fill_optionRequest();
29454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    fill_elapsedTime();
29554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    fill_iaid();
29654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    sendlength = sizeof(dhcp6_msg_t) - 524 + TT.length;
29754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  } else if (type == DHCP6REQUEST || type == DHCP6RELEASE || type == DHCP6RENEW)
29854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    sendlength = TT.request_length;
29954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dbg("Sending message type: %d\n", type);
30054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  sendlength = sendto(TT.sock1, &mesg, sendlength , 0,(struct sockaddr *)&addr6,
30154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          sizeof(struct sockaddr_in6 ));
30254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (sendlength <= 0) dbg("Error in sending message type: %d\n", type);
30354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
30454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
30554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleyuint8_t *get_msg_ptr(uint8_t *data, int data_length, int msgtype)
30654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
30754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint16_t type =  *((uint16_t*)data), length = *((uint16_t*)(data+2));
30854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
30954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  type = ntohs(type);
31054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (type == msgtype) return data;
31154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  length = ntohs(length);
31254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  while (type != msgtype) {
31354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    data_length -= (4 + length);
31454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    if (data_length <= 0) break;
31554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    data = data + 4 + length;
31654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    type = ntohs(*((uint16_t*)data));
31754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    length = ntohs(*((uint16_t*)(data+2)));
31854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    if (type == msgtype) return data;
31954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
32054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  return NULL;
32154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
32254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
32354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic uint8_t *check_server_id(uint8_t *data, int data_length)
32454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
32554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  return get_msg_ptr(data,  data_length, DHCP6_OPT_SERVERID);
32654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
32754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
32854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic int check_client_id(uint8_t *data, int data_length)
32954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
33054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if ((data = get_msg_ptr(data,  data_length, DHCP6_OPT_CLIENTID))) {
33154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    DUID one = *((DUID*)(data+4));
33254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    DUID two = *((DUID*)&mesg.options[4]);
33354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
33454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    if (!memcmp(&one, &two, sizeof(DUID))) return 1;
33554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
33654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  return 0;
33754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
33854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
33954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic int validate_ids()
34054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
34154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (!check_server_id(mymsg->dhcp6.options,
34254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    TT.status - ((char*)&mymsg->dhcp6.options[0] - (char*)mymsg) )) {
34354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    dbg("Invalid server id: %d\n");
34454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    return 0;
34554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
34654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (!check_client_id(mymsg->dhcp6.options,
34754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    TT.status - ((char*)&mymsg->dhcp6.options[0] - (char*)mymsg) )) {
34854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    dbg("Invalid client id: %d\n");
34954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    return 0;
35054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
35154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  return 1;
35254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
35354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
35454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void parse_ia_na(uint8_t *data, int data_length)
35554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
35654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint8_t *t = get_msg_ptr(data, data_length, DHCP6_OPT_IA_NA);
35754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  uint16_t iana_len, content_len = 0;
35854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
35954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  memset(&dhcp_data,0,sizeof(dhcp_data));
36054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (!t) return;
36154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
36254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  iana_len = ntohs(*((uint16_t*)(t+2)));
36354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dhcp_data.iaid = ntohl(*((uint32_t*)(t+4)));
36454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dhcp_data.t1 = ntohl(*((uint32_t*)(t+8)));
36554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dhcp_data.t2 = ntohl(*((uint32_t*)(t+12)));
36654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  t += 16;
36754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  iana_len -= 12;
36854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
36954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  while(iana_len > 0) {
37054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    uint16_t sub_type = ntohs(*((uint16_t*)(t)));
37154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
37254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    switch (sub_type) {
37354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      case DHCP6_OPT_IA_ADDR:
37454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        content_len = ntohs(*((uint16_t*)(t+2)));
37554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        memcpy(dhcp_data.ipaddr,t+4,16);
37654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        if (TT.state == DHCP6SOLICIT) {
37754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          if (TT.req_ip) {
37854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            struct addrinfo *res = NULL;
37954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
38054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            if(!getaddrinfo(TT.req_ip, NULL, NULL,&res)) {
38154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              dbg("Requesting IP: %s\n", TT.req_ip);
38254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              memcpy (&TT.input_socket6, res->ai_addr, res->ai_addrlen);
38354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              memcpy(t+4, TT.input_socket6.sin6_addr.__in6_u.__u6_addr8, 16);
38454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            } else xprintf("Invalid IP: %s\n",TT.req_ip);
38554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            freeaddrinfo(res);
38654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          }
38754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        }
38854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        dhcp_data.pf_lf = ntohl(*((uint32_t*)(t+20)));
38954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        dhcp_data.va_lf = ntohl(*((uint32_t*)(t+24)));
39054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        iana_len -= (content_len + 4);
39154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        t += (content_len + 4);
39254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        break;
39354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      case DHCP6_OPT_STATUS_CODE:
39454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        content_len = ntohs(*((uint16_t*)(t+2)));
39554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        dhcp_data.status_code = ntohs(*((uint16_t*)(t+4)));
39654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        iana_len -= (content_len + 4);
39754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        t += (content_len + 4);
39854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        break;
39954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      default:
40054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        content_len = ntohs(*((uint16_t*)(t+2)));
40154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        iana_len -= (content_len + 4);
40254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        t += (content_len + 4);
40354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        break;
40454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    }
40554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
40654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
40754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
40854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void write_pid(char *path)
40954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
41054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  int pidfile = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
41154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
41254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (pidfile > 0) {
41354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    char pidbuf[12];
41454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
41554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    sprintf(pidbuf, "%u", (unsigned)getpid());
41654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    write(pidfile, pidbuf, strlen(pidbuf));
41754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    close(pidfile);
41854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
41954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
42054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
42154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley// Creates environment pointers from RES to use in script
42254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic int fill_envp(DHCP_DATA *res)
42354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
42454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  int ret = setenv("interface", TT.interface_name, 1);
42554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
42654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (ret) return ret;
42754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  inet_ntop(AF_INET6, res->ipaddr, toybuf, INET6_ADDRSTRLEN);
42854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  ret = setenv("ip",(const char*)toybuf , 1);
42954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  return ret;
43054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
43154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
43254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley// Executes Script NAME.
43354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void run_script(DHCP_DATA *res,  char *name)
43454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
43554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  volatile int error = 0;
43654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  struct stat sts;
43754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  pid_t pid;
43854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  char *argv[3];
439547c9167565cf8a2bba8bd79850889101866814aRob Landley  char *script = (toys.optflags & FLAG_s) ? TT.script
440547c9167565cf8a2bba8bd79850889101866814aRob Landley    : "/usr/share/dhcp/default.script";
44154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
44254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (stat(script, &sts) == -1 && errno == ENOENT) return;
44354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (!res || fill_envp(res)) {
44454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    dbg("Failed to create environment variables.\n");
44554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    return;
44654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
44754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dbg("Executing %s %s\n", script, name);
44854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  argv[0] = (char*)script;
44954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  argv[1] = (char*)name;
45054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  argv[2] = NULL;
45154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  fflush(NULL);
45254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
45354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  pid = vfork();
45454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (pid < 0) {
45554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    dbg("Fork failed.\n");
45654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    return;
45754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
45854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (!pid) {
45954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    execvp(argv[0], argv);
46054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    error = errno;
46154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    _exit(111);
46254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
46354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (error) {
46454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    waitpid(pid, NULL, 0);
46554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    errno = error;
46654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    perror_msg("script exec failed");
46754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
46854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dbg("script complete.\n");
46954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
47054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
47154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void lease_fail()
47254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
47354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dbg("Lease failed.\n");
47454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  run_script(NULL, "leasefail");
475547c9167565cf8a2bba8bd79850889101866814aRob Landley  if (toys.optflags & FLAG_n) {
47654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    xclose(TT.sock);
47754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    xclose(TT.sock1);
47854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    error_exit("Lease Failed, Exiting.");
47954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
480547c9167565cf8a2bba8bd79850889101866814aRob Landley  if (toys.optflags & FLAG_b) {
48154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    dbg("Lease failed. Going to daemon mode.\n");
48254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    if (daemon(0,0)) perror_exit("daemonize");
483547c9167565cf8a2bba8bd79850889101866814aRob Landley    if (toys.optflags & FLAG_p) write_pid(TT.pidfile);
48454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    toys.optflags &= ~FLAG_b;
48554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    toys.optflags |= FLAG_f;
48654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
48754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
48854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
48954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley// Generic signal handler real handling is done in main funcrion.
49054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic void signal_handler(int sig)
49154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
49254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    dbg("Caught signal: %d\n", sig);
49354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    switch (sig) {
49454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    case SIGUSR1:
49554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      dbg("SIGUSR1.\n");
49654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      if (TT.state == DHCP6RELEASE || TT.state == DHCP6REQUEST ) {
49754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        TT.state = DHCP6SOLICIT;
49854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        set_timeout(0);
49954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        return;
50054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      }
50154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      dbg("SIGUSR1 sending renew.\n");
50254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      send_msg(DHCP6RENEW);
50354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      TT.state = DHCP6RENEW;
50454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      TT.retries = 0;
50554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      set_timeout(0);
50654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      break;
50754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    case SIGUSR2:
50854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      dbg("SIGUSR2.\n");
50954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      if (TT.state == DHCP6RELEASE) return;
51054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      if (TT.state != DHCP6CONFIRM ) return;
51154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      dbg("SIGUSR2 sending release.\n");
51254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      send_msg(DHCP6RELEASE);
51354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      TT.state = DHCP6RELEASE;
51454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      TT.retries = 0;
51554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      set_timeout(0);
51654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      break;
51754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    case SIGTERM:
51854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    case SIGINT:
51954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      dbg((sig == SIGTERM)?"SIGTERM.\n":"SIGINT.\n");
520547c9167565cf8a2bba8bd79850889101866814aRob Landley      if ((toys.optflags & FLAG_R) && TT.state == DHCP6CONFIRM)
521547c9167565cf8a2bba8bd79850889101866814aRob Landley        send_msg(DHCP6RELEASE);
52254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      if(sig == SIGINT) exit(0);
52354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      break;
52454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    default: break;
52554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
52654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
52754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
52854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley// signal setup for SIGUSR1 SIGUSR2 SIGTERM
52954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleystatic int setup_signal()
53054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
53154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  signal(SIGUSR1, signal_handler);
53254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  signal(SIGUSR2, signal_handler);
53354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  signal(SIGTERM, signal_handler);
53454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  signal(SIGINT, signal_handler);
53554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  return 0;
53654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
53754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
53854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landleyvoid dhcp6_main(void)
53954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley{
54054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  struct sockaddr_in6  sinaddr6;
54154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  int constone = 1;
54254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  fd_set rfds;
54354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
54454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  srand(time(NULL));
54554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  setlinebuf(stdout);
54654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dbg = dummy;
54754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  TT.state = DHCP6SOLICIT;
54854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
549547c9167565cf8a2bba8bd79850889101866814aRob Landley  if (toys.optflags & FLAG_v) dbg = logit;
55054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (!TT.interface_name) TT.interface_name = "eth0";
551547c9167565cf8a2bba8bd79850889101866814aRob Landley  if (toys.optflags & FLAG_p) write_pid(TT.pidfile);
55254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (!TT.retry) TT.retry = 3;
55354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (!TT.timeout) TT.timeout = 3;
55454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (!TT.errortimeout) TT.errortimeout = 20;
555547c9167565cf8a2bba8bd79850889101866814aRob Landley  if (toys.optflags & FLAG_S) {
55654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    openlog("DHCP6 :", LOG_PID, LOG_DAEMON);
55754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    dbg = logit;
55854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
55954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
56054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dbg("Interface: %s\n", TT.interface_name);
56154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dbg("pid file: %s\n", TT.pidfile);
56254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dbg("Retry count: %d\n", TT.retry);
56354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dbg("Timeout : %d\n", TT.timeout);
56454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  dbg("Error timeout: %d\n", TT.errortimeout);
56554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
56654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
56754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
56854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  setup_signal();
56954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  TT.sock1 = xsocket(PF_INET6, SOCK_DGRAM, 0);
57054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  memset(&sinaddr6, 0, sizeof(sinaddr6));
57154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  sinaddr6.sin6_family = AF_INET6;
57254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  sinaddr6.sin6_port = htons(DHCPC_CLIENT_PORT);
57354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  sinaddr6.sin6_scope_id = if_nametoindex(TT.interface_name);
57454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  sinaddr6.sin6_addr = in6addr_any ;
57554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
57654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  xsetsockopt(TT.sock1, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone));
57754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
57854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  if (bind(TT.sock1, (struct sockaddr *)&sinaddr6, sizeof(sinaddr6))) {
57954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    xclose(TT.sock1);
58054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    error_exit("bind failed");
58154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
58254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
58354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  mode_raw();
58454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  set_timeout(0);
58554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  for (;;) {
58654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    int maxfd = TT.sock;
58754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley
58854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    if (TT.sock >= 0) FD_SET(TT.sock, &rfds);
58954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    TT.retval = 0;
59054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    if ((TT.retval = select(maxfd + 1, &rfds, NULL, NULL, &TT.tv)) < 0) {
59154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      if(errno == EINTR) continue;
59254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      perror_exit("Error in select");
59354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    }
59454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    if (!TT.retval) {
59554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      if (TT.state == DHCP6SOLICIT || TT.state == DHCP6CONFIRM) {
59654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        dbg("State is solicit, sending solicit packet\n");
59754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        run_script(NULL, "deconfig");
59854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        send_msg(DHCP6SOLICIT);
59954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        TT.state = DHCP6SOLICIT;
60054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        TT.retries++;
60154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        if(TT.retries > TT.retry) set_timeout(TT.errortimeout);
60254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        else if (TT.retries == TT.retry) {
60354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          dbg("State is solicit, retry count is max.\n");
60454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          lease_fail();
60554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          set_timeout(TT.errortimeout);
60654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        } else set_timeout(TT.timeout);
60754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        continue;
60854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      } else if (TT.state == DHCP6REQUEST || TT.state == DHCP6RENEW ||
60954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              TT.state == DHCP6RELEASE) {
61054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        dbg("State is %d , sending packet\n", TT.state);
61154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        send_msg(TT.state);
61254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        TT.retries++;
61354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        if (TT.retries > TT.retry) set_timeout(TT.errortimeout);
61454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        else if (TT.retries == TT.retry) {
61554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          lease_fail();
61654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          set_timeout(TT.errortimeout);
61754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        } else set_timeout(TT.timeout);
61854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        continue;
61954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      }
62054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    } else if (FD_ISSET(TT.sock, &rfds)) {
62154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      if ((TT.status = read(TT.sock, toybuf, sizeof(toybuf))) <= 0) continue;
62254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      mymsg = (dhcp6_raw_t*)toybuf;
62354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      if (ntohs(mymsg->udph.dest) == 546 &&
62454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              !memcmp(mymsg->dhcp6.transaction_id, TT.transction_id, 3)) {
62554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        if (TT.state == DHCP6SOLICIT) {
62654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          if (mymsg->dhcp6.msgtype == DHCP6ADVERTISE ) {
62754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            if (!validate_ids()) {
62854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              dbg("Invalid id recieved, solicit.\n");
62954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              TT.state = DHCP6SOLICIT;
63054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              continue;
63154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            }
63254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            dbg("Got reply to request or solicit.\n");
63354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            TT.retries = 0;
63454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            set_timeout(0);
63554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            TT.request_length = TT.status - ((char*)&mymsg->dhcp6 - (char*)mymsg);
63654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            memcpy((uint8_t*)&mesg, &mymsg->dhcp6, TT.request_length);
63754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            parse_ia_na(mesg.options, TT.request_length);
63854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            dbg("Status code:%d\n", dhcp_data.status_code);
63954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            inet_ntop(AF_INET6, dhcp_data.ipaddr, toybuf, INET6_ADDRSTRLEN);
64054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            dbg("Advertiesed IP: %s\n", toybuf);
64154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            TT.state = DHCP6REQUEST;
64254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          } else {
64354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            dbg("Invalid solicit.\n");
64454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            continue;
64554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          }
64654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        } else if (TT.state == DHCP6REQUEST || TT.state == DHCP6RENEW ) {
64754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          if (mymsg->dhcp6.msgtype == DHCP6REPLY) {
64854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            if (!validate_ids()) {
64954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              dbg("Invalid id recieved, %d.\n", TT.state);
65054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              TT.state = DHCP6REQUEST;
65154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              continue;
65254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            }
65354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            dbg("Got reply to request or renew.\n");
65454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            TT.request_length = TT.status - ((char*)&mymsg->dhcp6 - (char*)mymsg);
65554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            memcpy((uint8_t*)&mesg, &mymsg->dhcp6, TT.request_length);
65654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            parse_ia_na(mymsg->dhcp6.options, TT.request_length);
65754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            dbg("Status code:%d\n", dhcp_data.status_code);
65854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            inet_ntop(AF_INET6, dhcp_data.ipaddr, toybuf, INET6_ADDRSTRLEN);
65954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            dbg("Got IP: %s\n", toybuf);
66054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            TT.retries = 0;
66154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            run_script(&dhcp_data, (TT.state == DHCP6REQUEST) ?
66254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              "request" : "renew");
663547c9167565cf8a2bba8bd79850889101866814aRob Landley            if (toys.optflags & FLAG_q) {
664547c9167565cf8a2bba8bd79850889101866814aRob Landley              if (toys.optflags & FLAG_R) send_msg(DHCP6RELEASE);
66554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              break;
66654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            }
66754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            TT.state = DHCP6CONFIRM;
66854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            set_timeout((dhcp_data.va_lf)?dhcp_data.va_lf:INT_MAX);
66954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            dbg("Setting timeout to intmax.");
670547c9167565cf8a2bba8bd79850889101866814aRob Landley            if (TT.state == DHCP6REQUEST || !(toys.optflags & FLAG_f)) {
67154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              dbg("Making it a daemon\n");
67254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              if (daemon(0,0)) perror_exit("daemonize");
67354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley              toys.optflags |= FLAG_f;
674547c9167565cf8a2bba8bd79850889101866814aRob Landley              if (toys.optflags & FLAG_p) write_pid(TT.pidfile);
67554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            }
67654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            dbg("Making it a foreground.\n");
67754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            continue;
67854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          } else {
67954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            dbg("Invalid reply.\n");
68054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley            continue;
68154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          }
68254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        } else if (TT.state == DHCP6RELEASE) {
68354a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          dbg("Got reply to release.\n");
68454a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          run_script(NULL, "release");
68554a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley          set_timeout(INT_MAX);
68654a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley        }
68754a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley      }
68854a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley    }
68954a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  }
69054a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  xclose(TT.sock1);
69154a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley  xclose(TT.sock);
69254a13f9ef4380501d3b12bb1f04408f5607d46eeRob Landley}
693