Changeset View
Changeset View
Standalone View
Standalone View
sbin/dhclient/dhclient.c
Show First 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
#define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin" | #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin" | ||||
cap_channel_t *capsyslog; | cap_channel_t *capsyslog; | ||||
time_t cur_time; | time_t cur_time; | ||||
time_t default_lease_time = 43200; /* 12 hours... */ | time_t default_lease_time = 43200; /* 12 hours... */ | ||||
char *path_dhclient_conf = _PATH_DHCLIENT_CONF; | const char *path_dhclient_conf = _PATH_DHCLIENT_CONF; | ||||
char *path_dhclient_db = NULL; | char *path_dhclient_db = NULL; | ||||
int log_perror = 1; | int log_perror = 1; | ||||
int privfd; | int privfd; | ||||
int nullfd = -1; | int nullfd = -1; | ||||
char hostname[_POSIX_HOST_NAME_MAX + 1]; | char hostname[_POSIX_HOST_NAME_MAX + 1]; | ||||
Show All 23 Lines | |||||
struct interface_info *ifi; | struct interface_info *ifi; | ||||
int findproto(char *, int); | int findproto(char *, int); | ||||
struct sockaddr *get_ifa(char *, int); | struct sockaddr *get_ifa(char *, int); | ||||
void routehandler(struct protocol *); | void routehandler(struct protocol *); | ||||
void usage(void); | void usage(void); | ||||
int check_option(struct client_lease *l, int option); | int check_option(struct client_lease *l, int option); | ||||
int check_classless_option(unsigned char *data, int len); | int check_classless_option(unsigned char *data, int len); | ||||
int ipv4addrs(char * buf); | int ipv4addrs(const char * buf); | ||||
int res_hnok(const char *dn); | int res_hnok(const char *dn); | ||||
int check_search(const char *srch); | int check_search(const char *srch); | ||||
char *option_as_string(unsigned int code, unsigned char *data, int len); | const char *option_as_string(unsigned int code, unsigned char *data, int len); | ||||
int fork_privchld(int, int); | int fork_privchld(int, int); | ||||
#define ROUNDUP(a) \ | #define ROUNDUP(a) \ | ||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) | ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) | ||||
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) | #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) | ||||
/* Minimum MTU is 68 as per RFC791, p. 24 */ | /* Minimum MTU is 68 as per RFC791, p. 24 */ | ||||
#define MIN_MTU 68 | #define MIN_MTU 68 | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
struct iaddr defaddr = { .len = 4 }; | struct iaddr defaddr = { .len = 4 }; | ||||
uint8_t curbssid[6]; | uint8_t curbssid[6]; | ||||
static void | static void | ||||
disassoc(void *arg) | disassoc(void *arg) | ||||
{ | { | ||||
struct interface_info *ifi = arg; | struct interface_info *_ifi = arg; | ||||
/* | /* | ||||
* Clear existing state. | * Clear existing state. | ||||
*/ | */ | ||||
if (ifi->client->active != NULL) { | if (_ifi->client->active != NULL) { | ||||
script_init("EXPIRE", NULL); | script_init("EXPIRE", NULL); | ||||
script_write_params("old_", | script_write_params("old_", | ||||
ifi->client->active); | _ifi->client->active); | ||||
if (ifi->client->alias) | if (_ifi->client->alias) | ||||
script_write_params("alias_", | script_write_params("alias_", | ||||
ifi->client->alias); | _ifi->client->alias); | ||||
script_go(); | script_go(); | ||||
} | } | ||||
ifi->client->state = S_INIT; | _ifi->client->state = S_INIT; | ||||
} | } | ||||
/* ARGSUSED */ | |||||
void | void | ||||
routehandler(struct protocol *p) | routehandler(struct protocol *p __unused) | ||||
{ | { | ||||
char msg[2048], *addr; | char msg[2048], *addr; | ||||
struct rt_msghdr *rtm; | struct rt_msghdr *rtm; | ||||
struct if_msghdr *ifm; | struct if_msghdr *ifm; | ||||
struct ifa_msghdr *ifam; | struct ifa_msghdr *ifam; | ||||
struct if_announcemsghdr *ifan; | struct if_announcemsghdr *ifan; | ||||
struct ieee80211_join_event *jev; | struct ieee80211_join_event *jev; | ||||
struct client_lease *l; | struct client_lease *l; | ||||
time_t t = time(NULL); | time_t t = time(NULL); | ||||
struct sockaddr *sa; | struct sockaddr_in *sa; | ||||
struct iaddr a; | struct iaddr a; | ||||
ssize_t n; | ssize_t n; | ||||
int linkstat; | int linkstat; | ||||
n = read(routefd, &msg, sizeof(msg)); | n = read(routefd, &msg, sizeof(msg)); | ||||
rtm = (struct rt_msghdr *)msg; | rtm = (struct rt_msghdr *)msg; | ||||
if (n < (ssize_t)sizeof(rtm->rtm_msglen) || | if (n < (ssize_t)sizeof(rtm->rtm_msglen) || | ||||
n < (ssize_t)rtm->rtm_msglen || | n < (ssize_t)rtm->rtm_msglen || | ||||
rtm->rtm_version != RTM_VERSION) | rtm->rtm_version != RTM_VERSION) | ||||
return; | return; | ||||
switch (rtm->rtm_type) { | switch (rtm->rtm_type) { | ||||
case RTM_NEWADDR: | case RTM_NEWADDR: | ||||
case RTM_DELADDR: | case RTM_DELADDR: | ||||
ifam = (struct ifa_msghdr *)rtm; | ifam = (struct ifa_msghdr *)rtm; | ||||
if (ifam->ifam_index != ifi->index) | if (ifam->ifam_index != ifi->index) | ||||
break; | break; | ||||
if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET) | if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET) | ||||
break; | break; | ||||
if (scripttime == 0 || t < scripttime + 10) | if (scripttime == 0 || t < scripttime + 10) | ||||
break; | break; | ||||
sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs); | sa = (struct sockaddr_in*)get_ifa((char *)(ifam + 1), ifam->ifam_addrs); | ||||
if (sa == NULL) | if (sa == NULL) | ||||
break; | break; | ||||
if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf)) | if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf)) | ||||
error("king bula sez: len mismatch"); | error("king bula sez: len mismatch"); | ||||
memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len); | memcpy(a.iabuf, &sa->sin_addr, a.len); | ||||
if (addr_eq(a, defaddr)) | if (addr_eq(a, defaddr)) | ||||
break; | break; | ||||
for (l = ifi->client->active; l != NULL; l = l->next) | for (l = ifi->client->active; l != NULL; l = l->next) | ||||
if (addr_eq(a, l->address)) | if (addr_eq(a, l->address)) | ||||
break; | break; | ||||
if (l == NULL) /* added/deleted addr is not the one we set */ | if (l == NULL) /* added/deleted addr is not the one we set */ | ||||
break; | break; | ||||
addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr); | addr = inet_ntoa(sa->sin_addr); | ||||
if (rtm->rtm_type == RTM_NEWADDR) { | if (rtm->rtm_type == RTM_NEWADDR) { | ||||
/* | /* | ||||
* XXX: If someone other than us adds our address, | * XXX: If someone other than us adds our address, | ||||
* should we assume they are taking over from us, | * should we assume they are taking over from us, | ||||
* delete the lease record, and exit without modifying | * delete the lease record, and exit without modifying | ||||
* the interface? | * the interface? | ||||
*/ | */ | ||||
warning("My address (%s) was re-added", addr); | warning("My address (%s) was re-added", addr); | ||||
▲ Show 20 Lines • Show All 658 Lines • ▼ Show 20 Lines | bootp(struct packet *packet) | ||||
dhcpoffer(packet); | dhcpoffer(packet); | ||||
} | } | ||||
void | void | ||||
dhcp(struct packet *packet) | dhcp(struct packet *packet) | ||||
{ | { | ||||
struct iaddrlist *ap; | struct iaddrlist *ap; | ||||
void (*handler)(struct packet *); | void (*handler)(struct packet *); | ||||
char *type; | const char *type; | ||||
switch (packet->packet_type) { | switch (packet->packet_type) { | ||||
case DHCPOFFER: | case DHCPOFFER: | ||||
handler = dhcpoffer; | handler = dhcpoffer; | ||||
type = "DHCPOFFER"; | type = "DHCPOFFER"; | ||||
break; | break; | ||||
case DHCPNAK: | case DHCPNAK: | ||||
handler = dhcpnak; | handler = dhcpnak; | ||||
Show All 21 Lines | |||||
void | void | ||||
dhcpoffer(struct packet *packet) | dhcpoffer(struct packet *packet) | ||||
{ | { | ||||
struct interface_info *ip = packet->interface; | struct interface_info *ip = packet->interface; | ||||
struct client_lease *lease, *lp; | struct client_lease *lease, *lp; | ||||
int i; | int i; | ||||
int arp_timeout_needed, stop_selecting; | int arp_timeout_needed, stop_selecting; | ||||
char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ? | const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ? | ||||
"DHCPOFFER" : "BOOTREPLY"; | "DHCPOFFER" : "BOOTREPLY"; | ||||
/* If we're not receptive to an offer right now, or if the offer | /* If we're not receptive to an offer right now, or if the offer | ||||
has an unrecognizable transaction id, then just drop it. */ | has an unrecognizable transaction id, then just drop it. */ | ||||
if (ip->client->state != S_SELECTING || | if (ip->client->state != S_SELECTING || | ||||
packet->interface->client->xid != packet->raw->xid || | packet->interface->client->xid != packet->raw->xid || | ||||
(packet->interface->hw_address.hlen != packet->raw->hlen) || | (packet->interface->hw_address.hlen != packet->raw->hlen) || | ||||
(memcmp(packet->interface->hw_address.haddr, | (memcmp(packet->interface->hw_address.haddr, | ||||
▲ Show 20 Lines • Show All 992 Lines • ▼ Show 20 Lines | write_client_lease(struct interface_info *ip, struct client_lease *lease, | ||||
fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n", | fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n", | ||||
t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, | t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, | ||||
t->tm_hour, t->tm_min, t->tm_sec); | t->tm_hour, t->tm_min, t->tm_sec); | ||||
fprintf(leaseFile, "}\n"); | fprintf(leaseFile, "}\n"); | ||||
fflush(leaseFile); | fflush(leaseFile); | ||||
} | } | ||||
void | void | ||||
script_init(char *reason, struct string_list *medium) | script_init(const char *reason, struct string_list *medium) | ||||
{ | { | ||||
size_t len, mediumlen = 0; | size_t len, mediumlen = 0; | ||||
struct imsg_hdr hdr; | struct imsg_hdr hdr; | ||||
struct buf *buf; | struct buf *buf; | ||||
int errs; | int errs; | ||||
if (medium != NULL && medium->string != NULL) | if (medium != NULL && medium->string != NULL) | ||||
mediumlen = strlen(medium->string); | mediumlen = strlen(medium->string); | ||||
Show All 18 Lines | script_init(const char *reason, struct string_list *medium) | ||||
if (errs) | if (errs) | ||||
error("buf_add: %m"); | error("buf_add: %m"); | ||||
if (buf_close(privfd, buf) == -1) | if (buf_close(privfd, buf) == -1) | ||||
error("buf_close: %m"); | error("buf_close: %m"); | ||||
} | } | ||||
void | void | ||||
priv_script_init(char *reason, char *medium) | priv_script_init(const char *reason, char *medium) | ||||
{ | { | ||||
struct interface_info *ip = ifi; | struct interface_info *ip = ifi; | ||||
if (ip) { | if (ip) { | ||||
ip->client->scriptEnvsize = 100; | ip->client->scriptEnvsize = 100; | ||||
if (ip->client->scriptEnv == NULL) | if (ip->client->scriptEnv == NULL) | ||||
ip->client->scriptEnv = | ip->client->scriptEnv = | ||||
malloc(ip->client->scriptEnvsize * sizeof(char *)); | malloc(ip->client->scriptEnvsize * sizeof(char *)); | ||||
Show All 11 Lines | if (ip) { | ||||
if (medium) | if (medium) | ||||
script_set_env(ip->client, "", "medium", medium); | script_set_env(ip->client, "", "medium", medium); | ||||
script_set_env(ip->client, "", "reason", reason); | script_set_env(ip->client, "", "reason", reason); | ||||
} | } | ||||
} | } | ||||
void | void | ||||
priv_script_write_params(char *prefix, struct client_lease *lease) | priv_script_write_params(const char *prefix, struct client_lease *lease) | ||||
{ | { | ||||
struct interface_info *ip = ifi; | struct interface_info *ip = ifi; | ||||
u_int8_t dbuf[1500], *dp = NULL; | u_int8_t dbuf[1500], *dp = NULL; | ||||
int i; | int i; | ||||
size_t len; | size_t len; | ||||
char tbuf[128]; | char tbuf[128]; | ||||
script_set_env(ip->client, prefix, "ip_address", | script_set_env(ip->client, prefix, "ip_address", | ||||
▲ Show 20 Lines • Show All 123 Lines • ▼ Show 20 Lines | if (len) { | ||||
pretty_print_option(i, dp, len, 0, 0)); | pretty_print_option(i, dp, len, 0, 0)); | ||||
} | } | ||||
} | } | ||||
snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry); | snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry); | ||||
script_set_env(ip->client, prefix, "expiry", tbuf); | script_set_env(ip->client, prefix, "expiry", tbuf); | ||||
} | } | ||||
void | void | ||||
script_write_params(char *prefix, struct client_lease *lease) | script_write_params(const char *prefix, struct client_lease *lease) | ||||
{ | { | ||||
size_t fn_len = 0, sn_len = 0, pr_len = 0; | size_t fn_len = 0, sn_len = 0, pr_len = 0; | ||||
struct imsg_hdr hdr; | struct imsg_hdr hdr; | ||||
struct buf *buf; | struct buf *buf; | ||||
int errs, i; | int errs, i; | ||||
if (lease->filename != NULL) | if (lease->filename != NULL) | ||||
fn_len = strlen(lease->filename); | fn_len = strlen(lease->filename); | ||||
▲ Show 20 Lines • Show All 247 Lines • ▼ Show 20 Lines | if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) | ||||
error("can't limit stdout: %m"); | error("can't limit stdout: %m"); | ||||
if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) | if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) | ||||
error("can't limit stderr: %m"); | error("can't limit stderr: %m"); | ||||
} | } | ||||
int | int | ||||
check_option(struct client_lease *l, int option) | check_option(struct client_lease *l, int option) | ||||
{ | { | ||||
char *opbuf; | const char *opbuf; | ||||
char *sbuf; | const char *sbuf; | ||||
/* we use this, since this is what gets passed to dhclient-script */ | /* we use this, since this is what gets passed to dhclient-script */ | ||||
opbuf = pretty_print_option(option, l->options[option].data, | opbuf = pretty_print_option(option, l->options[option].data, | ||||
l->options[option].len, 0, 0); | l->options[option].len, 0, 0); | ||||
sbuf = option_as_string(option, l->options[option].data, | sbuf = option_as_string(option, l->options[option].data, | ||||
l->options[option].len); | l->options[option].len); | ||||
▲ Show 20 Lines • Show All 243 Lines • ▼ Show 20 Lines | return (0); | ||||
return (1); | return (1); | ||||
} | } | ||||
/* Does buf consist only of dotted decimal ipv4 addrs? | /* Does buf consist only of dotted decimal ipv4 addrs? | ||||
* return how many if so, | * return how many if so, | ||||
* otherwise, return 0 | * otherwise, return 0 | ||||
*/ | */ | ||||
int | int | ||||
ipv4addrs(char * buf) | ipv4addrs(const char * buf) | ||||
{ | { | ||||
struct in_addr jnk; | struct in_addr jnk; | ||||
int count = 0; | int count = 0; | ||||
while (inet_aton(buf, &jnk) == 1){ | while (inet_aton(buf, &jnk) == 1){ | ||||
count++; | count++; | ||||
while (periodchar(*buf) || digitchar(*buf)) | while (periodchar(*buf) || digitchar(*buf)) | ||||
buf++; | buf++; | ||||
if (*buf == '\0') | if (*buf == '\0') | ||||
return (count); | return (count); | ||||
while (*buf == ' ') | while (*buf == ' ') | ||||
buf++; | buf++; | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
char * | const char * | ||||
option_as_string(unsigned int code, unsigned char *data, int len) | option_as_string(unsigned int code, unsigned char *data, int len) | ||||
{ | { | ||||
static char optbuf[32768]; /* XXX */ | static char optbuf[32768]; /* XXX */ | ||||
char *op = optbuf; | char *op = optbuf; | ||||
int opleft = sizeof(optbuf); | int opleft = sizeof(optbuf); | ||||
unsigned char *dp = data; | unsigned char *dp = data; | ||||
if (code > 255) | if (code > 255) | ||||
▲ Show 20 Lines • Show All 67 Lines • Show Last 20 Lines |