#include "unp.h" #include union val { int i_val; long l_val; struct linger linger_val; struct timeval timeval_val; } val; static char *sock_str_flag(union val *, int); static char *sock_str_int(union val *, int); static char *sock_str_linger(union val *, int); static char *sock_str_timeval(union val *, int); static char intres[128]; static char flagres[256]; static char lingerres[128]; static char timevalres[128]; struct sock_opts { const char *opt_str; int opt_level; int opt_name; char *(*opt_val_str)(union val *, int); } sock_opts[] = { {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, sock_str_flag}, {"SO_DEBUG", SOL_SOCKET, SO_DEBUG, sock_str_flag}, {"SO_DONTROUTE", SOL_SOCKET, SO_DONTROUTE, sock_str_flag}, {"SO_ERROR", SOL_SOCKET, SO_ERROR, sock_str_int }, {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, sock_str_flag}, {"SO_LINGER", SOL_SOCKET, SO_LINGER, sock_str_linger}, {"SO_OOBINLINE", SOL_SOCKET, SO_OOBINLINE, sock_str_flag}, {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, sock_str_int }, {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, sock_str_int }, {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, sock_str_int }, {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, sock_str_int }, {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, sock_str_timeval }, {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, sock_str_timeval }, {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, sock_str_flag}, // #ifdef SO_REUSEPORT // {"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, sock_str_flag}, // #else // {"SO_REUSEPORT", 0, 0, NULL}, // #endif {"SO_TYPE", SOL_SOCKET, SO_TYPE, sock_str_int}, // #ifdef SO_USELOOPBACK // {"SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag}, // #else // {"SO_USELOOPBACK", 0, 0, NULL}, // #endif }; int main(int argc, char * argv[]) { int fd; socklen_t len; struct sock_opts *ptr; for( ptr = sock_opts; ptr->opt_str != NULL; ptr++) { printf("%s: ", ptr->opt_str); if(ptr->opt_val_str == NULL) printf("(undefined)\n"); else { switch (ptr->opt_level) { case SOL_SOCKET: fd = Socket(AF_INET, SOCK_STREAM, 0); break; default: err_quit("Can't create fd for level %d\n", ptr->opt_level); } } len = sizeof(val); if(getsockopt(fd, ptr->opt_level, ptr->opt_name, &val, &len) == -1) { err_ret("getsockopt error"); } else { printf("default = %s\n", (*ptr->opt_val_str)(&val, len)); } close(fd); } } char *sock_str_flag(union val *ptr, int len) { if(len != sizeof(int)) snprintf(flagres, sizeof(flagres), "size(%d) not sizeof(int)", len); else snprintf(flagres, sizeof(flagres), "%s", (ptr->i_val == 0)? "off": "on"); return(flagres); } char *sock_str_int(union val *ptr, int len) { if(len != sizeof(int)) snprintf(intres, sizeof(intres), "size(%d) not sizeof(int)", len); else snprintf(intres, sizeof(intres), "%d", ptr->i_val); return(intres); } char *sock_str_linger(union val *ptr, int len) { if(len != sizeof(val.linger_val)) snprintf(lingerres, sizeof(lingerres), "size(%d) not sizeof(linger)", len); else snprintf(lingerres, sizeof(lingerres), "l_onoff = %d, l_linger = %d", ptr->linger_val.l_onoff, ptr->linger_val.l_linger); return(lingerres); } char *sock_str_timeval(union val *ptr, int len) { if(len != sizeof(val.timeval_val)) snprintf(timevalres, sizeof(timevalres), "size(%d) not sizeof(timeval)", len); else snprintf(timevalres, sizeof(timevalres), "%ld sec, %ld usec", ptr->timeval_val.tv_sec, ptr->timeval_val.tv_usec); return(timevalres); }