static int vsock_stream_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { int err; int len; struct sock *sk; struct vsock_sock *vsk; u64 val; if (level != AF_VSOCK) return -ENOPROTOOPT; err = get_user(len, optlen); if (err != 0) return err; #define COPY_OUT(_v) \ do { \ if (len < sizeof(_v)) \ return -EINVAL; \ \ len = sizeof(_v); \ if (copy_to_user(optval, &_v, len) != 0) \ return -EFAULT; \ \ } while (0) err = 0; sk = sock->sk; vsk = vsock_sk(sk); switch (optname) { case SO_VM_SOCKETS_BUFFER_SIZE: val = transport->get_buffer_size(vsk); COPY_OUT(val); break; case SO_VM_SOCKETS_BUFFER_MAX_SIZE: val = transport->get_max_buffer_size(vsk); COPY_OUT(val); break; case SO_VM_SOCKETS_BUFFER_MIN_SIZE: val = transport->get_min_buffer_size(vsk); COPY_OUT(val); break; case SO_VM_SOCKETS_CONNECT_TIMEOUT: { struct timeval tv; tv.tv_sec = vsk->connect_timeout / HZ; tv.tv_usec = (vsk->connect_timeout - tv.tv_sec * HZ) * (1000000 / HZ); COPY_OUT(tv); break; } default: return -ENOPROTOOPT; } err = put_user(len, optlen); if (err != 0) return -EFAULT; #undef COPY_OUT return 0; }
static int dialog_create (pinentry_t pinentry, dialog_t dialog) { int err = 0; int size_y; int size_x; int y; int x; int ypos; int xpos; int description_x = 0; int error_x = 0; CH *description = NULL; CH *error = NULL; CH *prompt = NULL; dialog->pinentry = pinentry; #define COPY_OUT(what) \ do \ if (pinentry->what) \ { \ what = utf8_to_local (pinentry->lc_ctype, pinentry->what); \ if (!what) \ { \ err = 1; \ pinentry->specific_err = ASSUAN_Locale_Problem; \ goto out; \ } \ } \ while (0) COPY_OUT (description); COPY_OUT (error); COPY_OUT (prompt); /* There is no pinentry->default_notok. Map it to pinentry->notok. */ #define default_notok notok #define MAKE_BUTTON(which,default) \ do \ { \ char *new = NULL; \ if (pinentry->default_##which || pinentry->which) \ { \ int len; \ char *msg; \ int i, j; \ \ msg = pinentry->which; \ if (! msg) \ msg = pinentry->default_##which; \ len = strlen (msg); \ \ new = malloc (len + 3); \ if (!new) \ { \ err = 1; \ pinentry->specific_err = ASSUAN_Out_Of_Core; \ goto out; \ } \ \ new[0] = '<'; \ for (i = 0, j = 1; i < len; i ++, j ++) \ { \ if (msg[i] == '_') \ { \ i ++; \ if (msg[i] == 0) \ /* _ at end of string. */ \ break; \ } \ new[j] = msg[i]; \ } \ \ new[j] = '>'; \ new[j + 1] = 0; \ } \ dialog->which = pinentry_utf8_to_local (pinentry->lc_ctype, \ new ? new : default); \ if (!dialog->which) \ { \ err = 1; \ pinentry->specific_err = ASSUAN_Locale_Problem; \ goto out; \ } \ } \ while (0) MAKE_BUTTON (ok, STRING_OK); if (!pinentry->one_button) MAKE_BUTTON (cancel, STRING_CANCEL); else dialog->cancel = NULL; if (!pinentry->one_button && pinentry->notok) MAKE_BUTTON (notok, STRING_NOTOK); else dialog->notok = NULL; getmaxyx (stdscr, size_y, size_x); /* Check if all required lines fit on the screen. */ y = 1; /* Top frame. */ if (description) { CH *start = description; int len = 0; do { collect_line (size_x - 4, &start, &len); if (len > description_x) description_x = len; y++; } while (start[len - 1]); y++; } if (pinentry->pin) { if (error) { CH *p = error; int err_x = 0; while (*p) { if (*(p++) == '\n') { if (err_x > error_x) error_x = err_x; y++; err_x = 0; } else err_x++; } if (err_x > error_x) error_x = err_x; y += 2; /* Error message. */ } y += 2; /* Pin entry field. */ } y += 2; /* OK/Cancel and bottom frame. */ if (y > size_y) { err = 1; pinentry->specific_err = ASSUAN_Too_Short; goto out; } /* Check if all required columns fit on the screen. */ x = 0; if (description) { int new_x = description_x; if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } if (pinentry->pin) { #define MIN_PINENTRY_LENGTH 40 int new_x; if (error) { new_x = error_x; if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } new_x = MIN_PINENTRY_LENGTH; if (prompt) { new_x += STRLEN (prompt) + 1; /* One space after prompt. */ } if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } /* We position the buttons after the first, second and third fourth of the width. Account for rounding. */ if (x < 3 * strlen (dialog->ok)) x = 3 * strlen (dialog->ok); if (dialog->cancel) if (x < 3 * strlen (dialog->cancel)) x = 3 * strlen (dialog->cancel); if (dialog->notok) if (x < 3 * strlen (dialog->notok)) x = 3 * strlen (dialog->notok); /* Add the frame. */ x += 4; if (x > size_x) { err = 1; pinentry->specific_err = ASSUAN_Too_Short; goto out; } dialog->pos = DIALOG_POS_NONE; dialog->pin_max = pinentry->pin_len; dialog->pin_loc = 0; dialog->pin_len = 0; ypos = (size_y - y) / 2; xpos = (size_x - x) / 2; move (ypos, xpos); addch (ACS_ULCORNER); hline (0, x - 2); move (ypos, xpos + x - 1); addch (ACS_URCORNER); move (ypos + 1, xpos + x - 1); vline (0, y - 2); move (ypos + y - 1, xpos); addch (ACS_LLCORNER); hline (0, x - 2); move (ypos + y - 1, xpos + x - 1); addch (ACS_LRCORNER); ypos++; if (description) { CH *start = description; int len = 0; do { int i; move (ypos, xpos); addch (ACS_VLINE); addch (' '); collect_line (size_x - 4, &start, &len); for (i = 0; i < len - 1; i++) { ADDCH (start[i]); } if (start[len - 1] != NULLCH && start[len - 1] != NLCH) ADDCH (start[len - 1]); ypos++; } while (start[len - 1]); move (ypos, xpos); addch (ACS_VLINE); ypos++; } if (pinentry->pin) { int i; if (error) { CH *p = error; i = 0; while (*p) { move (ypos, xpos); addch (ACS_VLINE); addch (' '); if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE) { attroff (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0)); attron (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0)); } else standout (); for (;*p && *p != NLCH; p++) if (i < x - 4) { i++; ADDCH (*p); } if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE) { attroff (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0)); attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0)); } else standend (); if (*p == '\n') p++; i = 0; ypos++; } move (ypos, xpos); addch (ACS_VLINE); ypos++; } move (ypos, xpos); addch (ACS_VLINE); addch (' '); dialog->pin_y = ypos; dialog->pin_x = xpos + 2; dialog->pin_size = x - 4; if (prompt) { CH *p = prompt; i = STRLEN (prompt); if (i > x - 4 - MIN_PINENTRY_LENGTH) i = x - 4 - MIN_PINENTRY_LENGTH; dialog->pin_x += i + 1; dialog->pin_size -= i + 1; while (i-- > 0) { ADDCH (*(p++)); } addch (' '); } for (i = 0; i < dialog->pin_size; i++) addch ('_'); ypos++; move (ypos, xpos); addch (ACS_VLINE); ypos++; } move (ypos, xpos); addch (ACS_VLINE); if (dialog->cancel || dialog->notok) { dialog->ok_y = ypos; /* Calculating the left edge of the left button, rounding down. */ dialog->ok_x = xpos + 2 + ((x - 4) / 3 - strlen (dialog->ok)) / 2; move (dialog->ok_y, dialog->ok_x); addstr (dialog->ok); if (! pinentry->pin && dialog->notok) { dialog->notok_y = ypos; /* Calculating the left edge of the middle button, rounding up. */ dialog->notok_x = xpos + x / 2 - strlen (dialog->notok) / 2; move (dialog->notok_y, dialog->notok_x); addstr (dialog->notok); } if (dialog->cancel) { dialog->cancel_y = ypos; /* Calculating the left edge of the right button, rounding up. */ dialog->cancel_x = xpos + x - 2 - ((x - 4) / 3 + strlen (dialog->cancel)) / 2; move (dialog->cancel_y, dialog->cancel_x); addstr (dialog->cancel); } } else { dialog->ok_y = ypos; /* Calculating the left edge of the OK button, rounding down. */ dialog->ok_x = xpos + x / 2 - strlen (dialog->ok) / 2; move (dialog->ok_y, dialog->ok_x); addstr (dialog->ok); } out: if (description) free (description); if (error) free (error); if (prompt) free (prompt); return err; }
static int dialog_create (pinentry_t pinentry, dialog_t dialog) { int err = 0; int size_y; int size_x; int y; int x; int ypos; int xpos; int description_x = 0; int error_x = 0; char *description = NULL; char *error = NULL; char *prompt = NULL; #define COPY_OUT(what) \ do \ if (pinentry->what) \ { \ what = pinentry_utf8_to_local (pinentry->lc_ctype, \ pinentry->what); \ if (!what) \ { \ err = 1; \ goto out; \ } \ } \ while (0) COPY_OUT (description); COPY_OUT (error); COPY_OUT (prompt); #define MAKE_BUTTON(which,default) \ do \ { \ char *new = NULL; \ if (pinentry->which) \ { \ int len = strlen (pinentry->which); \ new = malloc (len + 3); \ if (!new) \ { \ err = 1; \ goto out; \ } \ new[0] = '<'; \ memcpy (&new[1], pinentry->which, len); \ new[len + 1] = '>'; \ new[len + 2] = '\0'; \ } \ dialog->which = pinentry_utf8_to_local (pinentry->lc_ctype, \ new ? new : default); \ if (!dialog->which) \ { \ err = 1; \ goto out; \ } \ } \ while (0) MAKE_BUTTON (ok, STRING_OK); if (!pinentry->one_button) MAKE_BUTTON (cancel, STRING_CANCEL); else dialog->cancel = NULL; getmaxyx (stdscr, size_y, size_x); /* Check if all required lines fit on the screen. */ y = 1; /* Top frame. */ if (description) { char *start = description; int len = 0; do { collect_line (size_x - 4, &start, &len); if (len > description_x) description_x = len; y++; } while (start[len - 1]); y++; } if (pinentry->pin) { if (error) { char *p = error; int err_x = 0; while (*p) { if (*(p++) == '\n') { if (err_x > error_x) error_x = err_x; y++; err_x = 0; } else err_x++; } if (err_x > error_x) error_x = err_x; y += 2; /* Error message. */ } y += 2; /* Pin entry field. */ } y += 2; /* OK/Cancel and bottom frame. */ if (y > size_y) { err = 1; goto out; } /* Check if all required columns fit on the screen. */ x = 0; if (description) { int new_x = description_x; if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } if (pinentry->pin) { #define MIN_PINENTRY_LENGTH 40 int new_x; if (error) { new_x = error_x; if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } new_x = MIN_PINENTRY_LENGTH; if (prompt) new_x += strlen (prompt) + 1; /* One space after prompt. */ if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } /* We position the buttons after the first and second third of the width. Account for rounding. */ if (x < 2 * strlen (dialog->ok)) x = 2 * strlen (dialog->ok); if (dialog->cancel) if (x < 2 * strlen (dialog->cancel)) x = 2 * strlen (dialog->cancel); /* Add the frame. */ x += 4; if (x > size_x) { err = 1; goto out; } dialog->pos = DIALOG_POS_NONE; dialog->pin = pinentry->pin; dialog->pin_max = pinentry->pin_len; dialog->pin_loc = 0; dialog->pin_len = 0; ypos = (size_y - y) / 2; xpos = (size_x - x) / 2; move (ypos, xpos); addch (ACS_ULCORNER); hline (0, x - 2); move (ypos, xpos + x - 1); addch (ACS_URCORNER); move (ypos + 1, xpos + x - 1); vline (0, y - 2); move (ypos + y - 1, xpos); addch (ACS_LLCORNER); hline (0, x - 2); move (ypos + y - 1, xpos + x - 1); addch (ACS_LRCORNER); ypos++; if (description) { char *start = description; int len = 0; do { int i; move (ypos, xpos); addch (ACS_VLINE); addch (' '); collect_line (size_x - 4, &start, &len); for (i = 0; i < len - 1; i++) addch ((unsigned char) start[i]); if (start[len - 1] && start[len - 1] != '\n') addch ((unsigned char) start[len - 1]); ypos++; } while (start[len - 1]); move (ypos, xpos); addch (ACS_VLINE); ypos++; } if (pinentry->pin) { int i; if (error) { char *p = error; i = 0; while (*p) { move (ypos, xpos); addch (ACS_VLINE); addch (' '); if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE) { attroff (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0)); attron (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0)); } else standout (); for (;*p && *p != '\n'; p++) if (i < x - 4) { i++; addch ((unsigned char) *p); } if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE) { attroff (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0)); attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0)); } else standend (); if (*p == '\n') p++; i = 0; ypos++; } move (ypos, xpos); addch (ACS_VLINE); ypos++; } move (ypos, xpos); addch (ACS_VLINE); addch (' '); dialog->pin_y = ypos; dialog->pin_x = xpos + 2; dialog->pin_size = x - 4; if (prompt) { char *p = prompt; i = strlen (prompt); if (i > x - 4 - MIN_PINENTRY_LENGTH) i = x - 4 - MIN_PINENTRY_LENGTH; dialog->pin_x += i + 1; dialog->pin_size -= i + 1; while (i-- > 0) addch ((unsigned char) *(p++)); addch (' '); } for (i = 0; i < dialog->pin_size; i++) addch ('_'); ypos++; move (ypos, xpos); addch (ACS_VLINE); ypos++; } move (ypos, xpos); addch (ACS_VLINE); if (dialog->cancel) { dialog->ok_y = ypos; /* Calculating the left edge of the left button, rounding down. */ dialog->ok_x = xpos + 2 + ((x - 4) / 2 - strlen (dialog->ok)) / 2; move (dialog->ok_y, dialog->ok_x); addstr (dialog->ok); dialog->cancel_y = ypos; /* Calculating the left edge of the right button, rounding up. */ dialog->cancel_x = xpos + x - 2 - ((x - 4) / 2 + strlen (dialog->cancel)) / 2; move (dialog->cancel_y, dialog->cancel_x); addstr (dialog->cancel); } else { dialog->ok_y = ypos; /* Calculating the left edge of the OK button, rounding down. */ dialog->ok_x = xpos + x / 2 - strlen (dialog->ok) / 2; move (dialog->ok_y, dialog->ok_x); addstr (dialog->ok); } out: if (description) free (description); if (error) free (error); if (prompt) free (prompt); return err; }
/* * This is the ``callback function'' that is invoked by `sysctl_rtsock' in * order to copy data out. On each invocation, we get a buffer containing: * * + A `struct rt_msghdr'. The `rtm_type' member of this structure should * always be `RTM_GET'. * + A set of zero or more `struct sockaddr's describing the addresses * associated with the route. * * See the function `sysctl_rtsock' for further details. Some of the code * below is modeled after code in the FreeBSD `route' utility; in FreeBSD, see * the file `/usr/src/sbin/route/route.c'. */ static int get_one_ipforward( struct sysctl_req * req, const void * buf, size_t buf_size) { get_ipforward_env_t * env = (get_ipforward_env_t *) req; struct rt_msghdr * rtm = (struct rt_msghdr *) buf; struct rt_addrinfo rtinfo; struct sockaddr_in * sin; oskit_mib_in_addr_t dest; oskit_mib_in_addr_t mask; /* oskit_s32_t policy; */ oskit_mib_in_addr_t next_hop; oskit_s32_t if_index; oskit_u32_t type; oskit_u32_t proto; /* oskit_s32_t age; */ oskit_s32_t next_hop_as; oskit_s32_t metric1; oskit_s32_t metric2; oskit_s32_t metric3; oskit_s32_t metric4; oskit_s32_t metric5; /*********************************************************************/ if (rtm->rtm_version != RTM_VERSION) { /* A message we don't understand? This should never happen. */ assert(!"Received an unknown type of message."); goto done; } if (rtm->rtm_type != RTM_GET) { /* A message we don't understand? This should never happen. */ assert(!"Received an unknown type of message."); goto done; } /* * Figure out what the socket addresses mean; i.e., assign them to the * appropriate elements of the `rtinfo.rti_info' array. */ rtinfo.rti_addrs = rtm->rtm_addrs; rt_xaddrs(((char *) (rtm + 1)), ((char *) rtm) + rtm->rtm_msglen, &rtinfo); /* From `rtinfo', decode the fields of our table row. */ sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_DST]; if (!sin) /* No destination address?! */ goto done; dest = sin->sin_addr.s_addr; sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_NETMASK]; if (!sin) /* No network mask?! */ goto done; mask = sin->sin_addr.s_addr; /* * XXX --- RFC 1354 says that this should be an encoding of the IP TOS. * I don't understand how I'm supposed to determine that for a route. * The TOS is associated with a particular socket, not a route, right? */ /* policy = ...; */ if (rtm->rtm_flags & RTF_LOCAL) { next_hop = INADDR_ANY; /* See RFC 1354. */ } else { sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_GATEWAY]; if (!sin) /* No next hop address?! */ goto done; switch (sin->sin_family) { case AF_INET: next_hop = sin->sin_addr.s_addr; break; case AF_LINK: /* * The gateway address is a link-layer address. This * means that we're talking about one of our own * interfaces. * * RFC 1213 says (for `ipRouteNextHop'): ``In the case * of a route bound to an interface which is realized * via a broadcast media, the value of this field is * the agent's IP address on that interface.'' * * RFC 1354 says (for `ipForwardNextHop'): ``On remote * routes, the address of the next system en route; * Otherwise, 0.0.0.0.'' * * We follow RFC 1354 because we *are* implementing the * `ipForwardTable' after all. Plus, we don't have our * IP address on the interface handy at this point. * (`dest' isn't it. `dest' has had the subnet mask * applied to it, so it's missing parts of our addr.) */ #if 1 next_hop = INADDR_ANY; #else sdl = (struct sockaddr_dl *) sin; switch (sdl->sdl_type) { case IFT_ETHER: /* List other broadcast media here. */ next_hop = /* Our IP address. Not `dest'. */; break; default: next_hop = INADDR_ANY; break; } #endif break; default: assert(!"Received an unrecognized kind of next-hop"); next_hop = INADDR_ANY; break; } } if_index = rtm->rtm_index; type = ((rtm->rtm_flags & RTF_GATEWAY) ? OSKIT_MIB_IP_FORWARD_TYPE_REMOTE : OSKIT_MIB_IP_FORWARD_TYPE_LOCAL); proto = ((rtm->rtm_flags & RTF_LOCAL) ? OSKIT_MIB_IP_FORWARD_PROTO_LOCAL : (rtm->rtm_flags & RTF_DYNAMIC) ? OSKIT_MIB_IP_FORWARD_PROTO_ICMP : (rtm->rtm_flags & RTF_STATIC) ? OSKIT_MIB_IP_FORWARD_PROTO_NETMGMT : OSKIT_MIB_IP_FORWARD_PROTO_OTHER ); /* XXX --- I don't believe that route age is stored anywhere. */ /* age = ...; */ next_hop_as = 0; /* See IETF RFC 1354. */ /* * XXX --- I don't really understand the semantics of these values; * e.g., are they supposed to have well-defined meanings? I've just * picked the most interesting set of metrics from our route info. */ metric1 = (rtm->rtm_flags & RTF_UP); /* Is this route usable? */ metric2 = rtm->rtm_rmx.rmx_hopcount; /* Max hops expected. */ metric3 = rtm->rtm_rmx.rmx_sendpipe; /* Out delay-b'width product */ metric4 = rtm->rtm_rmx.rmx_rtt; /* Estimated round trip time */ metric5 = rtm->rtm_rmx.rmx_rttvar; /* Estimated RTT variance. */ /*********************************************************************/ /* * Process the entry. */ if (ipforward_match(dest, mask, /* policy, */ next_hop, if_index, type, proto, /* age, */ next_hop_as, metric1, metric2, metric3, metric4, metric5, env->args.matching)) { if (env->args.start_row > 0) { /* Skip this row. */ env->args.start_row--; } else if (env->args.want_rows > 0) { /* Accumulate this row. */ #define COPY_OUT(slot_type, slot_name) \ oskit_mib_##slot_type##_set( \ &(env->args.table->ip_forward_##slot_name), \ slot_name) #define CLEAR_OUT(slot_type, slot_name) \ oskit_mib_##slot_type##_clear( \ &(env->args.table->ip_forward_##slot_name)) COPY_OUT(mib_in_addr, dest); COPY_OUT(mib_in_addr, mask); CLEAR_OUT(s32, policy); /* XXX */ COPY_OUT(mib_in_addr, next_hop); COPY_OUT(s32, if_index); COPY_OUT(u32, type); COPY_OUT(u32, proto); CLEAR_OUT(s32, age); /* XXX */ COPY_OUT(s32, next_hop_as); COPY_OUT(s32, metric1); COPY_OUT(s32, metric2); COPY_OUT(s32, metric3); COPY_OUT(s32, metric4); COPY_OUT(s32, metric5); #undef COPY_OUT (*env->args.out_rows)++; env->args.table++; env->args.want_rows--; } else { /* Indicate that the table filled up. */ *env->args.more_rows = 1; } } done: /* Indicate to the `sysctl_rtsock' function that no error occurred. */ return 0; }
/* * This is the ``callback function'' that is invoked by `sysctl_rtsock' in * order to copy data out. See the comments before `get_one_ipaddr' for * general information about the data we receive on each callback. */ static int get_one_ipnettomedia( struct sysctl_req * req, const void * buf, size_t buf_size) { get_ipnettomedia_env_t * env = (get_ipnettomedia_env_t *) req; struct ifa_msghdr * ifam = (struct ifa_msghdr *) buf; struct rt_addrinfo rtinfo; struct sockaddr_in * sin; oskit_u32_t if_index; /* oskit_mib_string_t phys_address; --- not needed. */ oskit_mib_in_addr_t net_address; oskit_u32_t type; /*********************************************************************/ /* * We get physical addresses from `RTM_IFINFO' messages, and we get IP * addresses from subsequent `RTM_NEWADDR' messages. Note that there * may be more than one IP address per interface. * */ if (ifam->ifam_type == RTM_IFINFO) { struct if_msghdr * ifm = (struct if_msghdr *) buf; struct sockaddr_dl * sdl = (struct sockaddr_dl *) (ifm+1); extract_phys_address(sdl, env); DEBUG_SET_STATE((env->state = SEEN_IFINFO)); goto done; } if (ifam->ifam_type != RTM_NEWADDR) { assert(!"Received an unknown type of message."); goto done; } DEBUG_CHECK_STATE((env->state == SEEN_IFINFO)); /*********************************************************************/ /* If we don't have a valid physical address, bail early. */ if (!env->phys_address.str) goto done; /* * Figure out what the socket addresses mean; i.e., assign them to the * appropriate elements of the `rtinfo.rti_info' array. */ rtinfo.rti_addrs = ifam->ifam_addrs; rt_xaddrs(((char *) (ifam + 1)), ((char *) ifam) + ifam->ifam_msglen, &rtinfo); /* * From `env->phys_address' and `rtinfo', decode the fields of our * table row. */ if_index = ifam->ifam_index; /* phys_address = env->phys_address; --- why bother? */ sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_IFA]; if (!sin) /* No interface address?! */ goto done; net_address = sin->sin_addr.s_addr; /* * XXX --- Perhaps this isn't right, but I'm not sure what is. The * UCD-SNMP code returns `static' for permanent ARP cache entries and * `dynamic' for others. But that doesn't seem right: what exactly is * dynamic about a host's own IP-->Ethernet mappings? */ type = OSKIT_MIB_IP_NET_TO_MEDIA_TYPE_STATIC; /*********************************************************************/ /* * Process the entry. */ if (ipnettomedia_match(if_index, env->phys_address, net_address, type, env->args.matching)) { if (env->args.start_row > 0) { /* Skip this row. */ env->args.start_row--; } else if (env->args.want_rows > 0) { /* Accumulate this row. */ #define COPY_OUT(slot_type, slot_name) \ oskit_mib_##slot_type##_set( \ &(env->args.table->ip_net_to_media_##slot_name), \ slot_name) COPY_OUT(u32, if_index); copy_out_str(&(env->args.table-> ip_net_to_media_phys_address), &(env->phys_address)); COPY_OUT(mib_in_addr, net_address); COPY_OUT(u32, type); #undef COPY_OUT (*env->args.out_rows)++; env->args.table++; env->args.want_rows--; } else { /* Indicate that the table filled up. */ *env->args.more_rows = 1; } } done: /* Indicate to the `sysctl_rtsock' function that no error occurred. */ return 0; }
/* * This is the ``callback function'' that is invoked by `sysctl_rtsock' in * order to copy data out. The data that is given to us is as follows: * * + First, we are called with a buffer containing a `struct if_msghdr', with * the type member set to `RTM_IFINFO'. This signals the start of a group * of callbacks about a particular interface. The `if_msghdr' is followed * by zero of more `struct sockaddr_dl's (in the same buffer). * * + Subsequent callbacks will receive a `struct ifa_msghdr' (with its type * member set to `RTM_NEWADDR') followed immediatley by zero or more * `struct sockaddr_in's. This describes a particular group of (IP) * addresses for an interface. * * These callbacks are performed one for each interface. I.e., for each * interface, we will receive a `RTM_IFINFO' callback followed by zero or more * `RTM_NEWADDR' callbacks. * * See the function `sysctl_rtsock' for further details. Some of the code * below is modeled after code in the FreeBSD `ifconfig' utility; in FreeBSD, * see the file `/usr/src/sbin/ifconfig/ifconfig.c'. */ static int get_one_ipaddr( struct sysctl_req * req, const void * buf, size_t buf_size) { get_ipaddr_env_t * env = (get_ipaddr_env_t *) req; struct ifa_msghdr * ifam = (struct ifa_msghdr *) buf; struct rt_addrinfo rtinfo; struct sockaddr_in * sin; oskit_mib_in_addr_t addr; oskit_u32_t if_index; oskit_mib_in_addr_t net_mask; oskit_u32_t bcast_addr; oskit_u16_t reasm_max_size; /*********************************************************************/ /* * Mainly, we care about `RTM_NEWADDR' messages. Each of these * messages contains a `struct ifa_msghdr' followed by a set of socket * addresses (`struct sockaddr_in's). * * We need `RTM_IFINFO' messages only to set our `env->ifinfo_flags'. * One of these messages contains a `struct if_msghdr' (followed by a * set of `struct sockaddr_dl's, which we don't care about here). */ if (ifam->ifam_type == RTM_IFINFO) { env->ifinfo_flags = ((struct if_msghdr *) buf)->ifm_flags; DEBUG_SET_STATE((env->state = SEEN_IFINFO)); goto done; } if (ifam->ifam_type != RTM_NEWADDR) { assert(!"Received an unknown type of message."); goto done; } DEBUG_CHECK_STATE((env->state == SEEN_IFINFO)); /*********************************************************************/ /* * Figure out what the socket addresses mean; i.e., assign them to the * appropriate elements of the `rtinfo.rti_info' array. */ rtinfo.rti_addrs = ifam->ifam_addrs; rt_xaddrs(((char *) (ifam + 1)), ((char *) ifam) + ifam->ifam_msglen, &rtinfo); /* * From `rtinfo', decode the fields of our table row. */ sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_IFA]; if (!sin) /* No interface address?! */ goto done; addr = sin->sin_addr.s_addr; if_index = ifam->ifam_index; sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_NETMASK]; if (!sin) /* No network mask?! */ goto done; net_mask = sin->sin_addr.s_addr; /* XXX --- Default `bcast_addr' to one. */ bcast_addr = 1; /* * For point-to-point links, `rti_info[RTAX_BRD]' holds the destination * address. So, one must check for the `IFF_BROADCAST' flag. */ if (env->ifinfo_flags & IFF_BROADCAST) { sin = (struct sockaddr_in *) rtinfo.rti_info[RTAX_BRD]; if (sin) bcast_addr = (ntohl(sin->sin_addr.s_addr) & 1); } /* * I'm pretty sure that the `reasm_max_size' is `IP_MAXPACKET' for all * interfaces. */ reasm_max_size = IP_MAXPACKET; /*********************************************************************/ /* * Process the entry. */ if (ipaddr_match(addr, if_index, net_mask, bcast_addr, reasm_max_size, env->args.matching)) { if (env->args.start_row > 0) { /* Skip this row. */ env->args.start_row--; } else if (env->args.want_rows > 0) { /* Accumulate this row. */ #define COPY_OUT(slot_type, slot_name) \ oskit_mib_##slot_type##_set( \ &(env->args.table->ip_ad_ent_##slot_name), \ slot_name) COPY_OUT(mib_in_addr, addr); COPY_OUT(u32, if_index); COPY_OUT(mib_in_addr, net_mask); COPY_OUT(u32, bcast_addr); COPY_OUT(u16, reasm_max_size); #undef COPY_OUT (*env->args.out_rows)++; env->args.table++; env->args.want_rows--; } else { /* Indicate that the table filled up. */ *env->args.more_rows = 1; } } done: /* Indicate to the `sysctl_rtsock' function that no error occurred. */ return 0; }