Ejemplo n.º 1
0
/*****************************************************************************
 函数名称  : add_pcp_rule
 功能描述  : 对参数进行封装,并发送到pcp client
 输入参数  : 见函数声明
             lifetime目前没有意义,赋0即可。在没有收到delete mapping之前,pcp client
             一直refresh,将lifetime当作无限长处理。lifetime只在miniupnpd中维护,超期后
             删除,删除的时候确保通知给pcp client即可。
 输出参数  : No
 返 回 值  : No
*****************************************************************************/
void add_pcp_rule(unsigned short eport, int proto, unsigned int lifetime, int enabled,
                    const char *local_ip, unsigned short iport)
{
    PARA_TO_PCP_PROC_ST pcp_para;
    char wan_ip[IPV4_ADDRESS_LEN] = {0};

    NP_UPNP_DEBUG("add_pcp_rule entered: eport:%d, proto:%d, iport:%d", eport, proto, iport);

    if (NULL == local_ip)
    {
        NP_UPNP_ERROR("local ip is NULL, be carefully.\n");
    }

    memset(&pcp_para, 0, sizeof(pcp_para));
    // wanip作为inip,eport作为iport
    if ((getifaddr(ext_if_name, wan_ip, sizeof(wan_ip)) < 0) || (0 == strlen(wan_ip)))
    {
        NP_UPNP_ERROR("Failed to get wan ip.\n");
    }
    else
    {
        //eport作为iport
        fill_pcp_process_para(&pcp_para, iport, wan_ip, eport, proto,
                                lifetime, enabled, local_ip);
        send_msg_to_pcp_client(ATP_MSG_PCP_ADD_PORTMAP, &pcp_para);
    }
}
Ejemplo n.º 2
0
static bool parse_listen_faces(char str[], ccarray_t * faces)
{
  static const char delims[] = " \t\n,;";
  char * tok;

  tok = strtok(str, delims);
  while ( tok && ccarray_size(faces) < ccarray_capacity(faces) ) {

    uint32_t address = 0;
    uint16_t port = 0;

    if ( getifaddr(tok, &address, &port) == -1 ) {
      fprintf(stderr, "FATAL: Can't get address for '%s': %s\n", tok, strerror(errno));
      fprintf(stderr, "Check if device name is valid and device is up\n");
      return false;
    }

    if ( !port ) {
      fprintf(stderr, "No port specified in '%s'\n", tok);
      return false;
    }

    ccarray_push_back(faces, &(struct sockaddr_in ) {
          .sin_family = AF_INET,
          .sin_addr.s_addr = htonl(address),
          .sin_port = htons(port),
          .sin_zero = { 0 }
        });

    tok = strtok(NULL, delims);
  }
Ejemplo n.º 3
0
int ip6up_main(int argc, char **argv)
{
	char *wan_ifname = safe_getenv("IFNAME");
	char *llremote = safe_getenv("LLREMOTE");

	if (!wan_ifname || strlen(wan_ifname) <= 0)
		return 0;

	nvram_set("ipv6_ll_remote", llremote);

        switch (get_ipv6_service()) {
                case IPV6_NATIVE:
                case IPV6_NATIVE_DHCP:
			wait_ppp_count = 10;
			while ((!is_intf_up(wan_ifname) || !getifaddr(wan_ifname, AF_INET6, 0))
				&& (wait_ppp_count-- > 0))
				sleep(1);
			break;
		default:
			wait_ppp_count = 0;
			break;
	}

	if (wait_ppp_count != -2)
	{
		wan6_up(wan_ifname);	
		start_firewall(0, 0);
	}

	return 0;
}
Ejemplo n.º 4
0
static void FillPublicAddressResponse(unsigned char * resp, in_addr_t senderaddr)
{
#ifndef MULTIPLE_EXTERNAL_IP
	char tmp[16];
	UNUSED(senderaddr);

	if(use_ext_ip_addr) {
        inet_pton(AF_INET, use_ext_ip_addr, resp+8);
	} else {
		if(!ext_if_name || ext_if_name[0]=='\0') {
			resp[3] = 3;	/* Network Failure (e.g. NAT box itself
			                 * has not obtained a DHCP lease) */
		} else if(getifaddr(ext_if_name, tmp, INET_ADDRSTRLEN) < 0) {
			syslog(LOG_ERR, "Failed to get IP for interface %s", ext_if_name);
			resp[3] = 3;	/* Network Failure (e.g. NAT box itself
			                 * has not obtained a DHCP lease) */
		} else {
			inet_pton(AF_INET, tmp, resp+8); /* ok */
		}
	}
#else
	struct lan_addr_s * lan_addr;

	for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) {
		if( (senderaddr & lan_addr->mask.s_addr)
		   == (lan_addr->addr.s_addr & lan_addr->mask.s_addr)) {
			memcpy(resp+8, &lan_addr->ext_ip_addr,
			       sizeof(lan_addr->ext_ip_addr));
			break;
		}
	}
#endif
}
Ejemplo n.º 5
0
/* Set address by interface name, ip address or hostname */
int generic_addr(struct sockaddr_in *addr, struct vtun_addr *vaddr)
{
    struct hostent *hent;
    memset(addr, 0, sizeof(struct sockaddr_in));

    addr->sin_family = AF_INET;

    switch (vaddr->type) {
    case VTUN_ADDR_IFACE:
	if (!(addr->sin_addr.s_addr = getifaddr(vaddr->name))) {
	    vtun_syslog(LOG_ERR,
			"Can't get address of interface %s", vaddr->name);
	    return -1;
	}
	break;
    case VTUN_ADDR_NAME:
	if (!(hent = gethostbyname(vaddr->name))) {
	    vtun_syslog(LOG_ERR,
			"Can't resolv local address %s", vaddr->name);
	    return -1;
	}
	addr->sin_addr.s_addr = *(unsigned long *) hent->h_addr;
	break;
    default:
	addr->sin_addr.s_addr = INADDR_ANY;
	break;
    }

    if (vaddr->port)
	addr->sin_port = htons(vaddr->port);

    return 0;
}
Ejemplo n.º 6
0
static bool
set_ipv4_multicast_leave( int socket, struct in_addr maddr, char *ifname ) {
  assert( ifname != NULL );

  if ( !IN_MULTICAST( ntohl( maddr.s_addr ) ) ) {
    return false;
  }

  unsigned int n_users = 0;
  delete_user_from_multicast_group( maddr, &n_users );
  if ( n_users > 0 ) {
    // Still used.
    return true;
  }

  struct ip_mreq mreq;
  memset( &mreq, 0, sizeof( mreq ) );
  mreq.imr_multiaddr = maddr;
  if ( !getifaddr( ifname, &mreq.imr_interface ) ) {
    return false;
  }

  int ret = setsockopt( socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
                        ( char * ) &mreq, sizeof( mreq ) );
  if ( ret < 0 ) {
    char buf[ 256 ];
    char *error_string = safe_strerror_r( errno, buf, sizeof( buf ) );
    error( "Failed to send a leave group ( socket = %d, ret = %d, errno = %s [%d] ).",
           socket, ret, error_string, errno );
    return false;
  }

  return true;
}
Ejemplo n.º 7
0
VALUE netif_get_addr(VALUE self)
{
	VALUE ifname = rb_iv_get(self, "@ifname");
	char buf[128];

	getifaddr(StringValuePtr(ifname), buf, sizeof(buf));
	return rb_str_new2(buf);
}
Ejemplo n.º 8
0
/**
 * get the connection status
 * return values :
 *  0 - Unconfigured
 *  1 - Connecting
 *  2 - Connected
 *  3 - PendingDisconnect
 *  4 - Disconnecting
 *  5 - Disconnected */
int
get_wan_connection_status(const char * ifname)
{
	char addr[INET_ADDRSTRLEN];
	int r;

	/* we need a better implementation here.
	 * I'm afraid it should be device specific */
	r = getifaddr(ifname, addr, INET_ADDRSTRLEN);
	return (r < 0) ? STATUS_DISCONNECTED : STATUS_CONNECTED;
}
Ejemplo n.º 9
0
int get_local_address(const std::string &eth_name, std::string &local_address)
{
    // get local address
    uint32_t ip; 
    if (getifaddr(AF_INET, 0, eth_name.c_str(), &ip) != 0){
	return -1;
    }
    char ip_str[INET_ADDRSTRLEN]; 
    if(inet_ntop(AF_INET, &ip, ip_str, sizeof (ip_str)) == NULL){
	return -1;
    } 
    local_address = ip_str;
    return 0;
}
Ejemplo n.º 10
0
int main(int argc, char * * argv) {
	char addr[64];
	if(argc < 2) {
		fprintf(stderr, "Usage:\t%s interface_name\n", argv[0]);
		return 1;
	}
	openlog("testgetifaddr", LOG_CONS|LOG_PERROR, LOG_USER);
	if(getifaddr(argv[1], addr, sizeof(addr)) < 0) {
		fprintf(stderr, "Cannot get address for interface %s.\n", argv[1]);
		return 1;
	}
	printf("Interface %s has IP address %s.\n", argv[1], addr);
	return 0;
}
Ejemplo n.º 11
0
bool
update_interface_state() {
  assert( vxlan != NULL );

  struct in_addr addr;
  if ( getifaddr( vxlan->ifname, &addr ) ) {
    vxlan->active = true;
  }
  else {
    vxlan->active = false;
  }

  return true;
}
Ejemplo n.º 12
0
static bool
set_ipv4_multicast_join_and_iface( int socket, struct in_addr maddr, char *ifname ) {
  assert( ifname != NULL );

  if ( !IN_MULTICAST( ntohl( maddr.s_addr ) ) ) {
    return false;
  }

  unsigned int n_users = 0;
  add_user_into_multicast_group( maddr, &n_users );
  if ( n_users > 1 ) {
    // Already joined.
    return true;
  }
  else if ( n_users != 1 ) {
    return false;
  }

  struct ip_mreq mreq;
  memset( &mreq, 0, sizeof( mreq ) );
  mreq.imr_multiaddr = maddr;
  if ( !getifaddr( ifname, &mreq.imr_interface ) ) {
    return false;
  }

  char buf[ 256 ];

  int ret = setsockopt( socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                        ( char * ) &mreq, sizeof( mreq ) );
  if ( ret < 0 ) {
    char *error_string = safe_strerror_r( errno, buf, sizeof( buf ) );
    error( "Failed to send a membership report ( socket = %d, ret = %d, errno = %s [%d] ).",
           socket, ret, error_string, errno );
    return false;
  }

  ret = setsockopt( socket, IPPROTO_IP, IP_MULTICAST_IF,
                    ( char * ) &mreq.imr_interface, sizeof( mreq.imr_interface ) );
  if ( ret < 0 ) {
    char *error_string = safe_strerror_r( errno, buf, sizeof( buf ) );
    error( "Failed to set a network interface ( socket = %d, ret = %d, errno = %s [%d] ).",
           socket, ret, error_string, errno );
    return false;
  }

  return true;
}
Ejemplo n.º 13
0
static void check_and_set_comm_if(void)
{
#ifndef RTCONFIG_RALINK
	const char *ipaddr;
	char buf_ip[32];

	ipaddr = getifaddr("vlan2", AF_INET, GIF_PREFIXLEN);
	//_dprintf("%s: %s\n", __func__, ipaddr);
	if(!ipaddr || (ipaddr && strncmp("169.254", ipaddr, 7))) {
		pick_a_random_ipv4(buf_ip);
		ifconfig("vlan2", IFUP, buf_ip, "255.255.0.0");
	}

	if(!check_if_route_exist("vlan2", "169.254.0.1", "255.255.255.255"))
		route_add("vlan2", 0, "169.254.0.1", "0.0.0.0", "255.255.255.255");
#endif
}
Ejemplo n.º 14
0
int
main(void)
{
	char *status;
	/*char *avgs;*/
	char *tmcentral;
        char *cpu;
	char *battery;
	char *ifaddr;
	char *temp;
        int i = 0;

	if (!(dpy = XOpenDisplay(NULL))) {
		fprintf(stderr, "dwmstatus: cannot open display.\n");
		return 1;
	}

        /* Clear old_stats for cpu usage*/
        for(i = 0; i < 10; ++i)
            old_stats[i] = 0;

	for (;;sleep(1)) {
		/*avgs = loadavg();*/
                cpu = cpu_usage();
		tmcentral = mktimes("%Y-%m-%d %H:%M:%S", tzcentral);
		battery = getbattery();
		ifaddr = getifaddr();
		temp = gettemp();

		status = smprintf("%s | %s BAT %s | CPU %s | %s",
				temp, ifaddr, battery, cpu, tmcentral);
		setstatus(status);
		/*free(avgs);*/
		free(tmcentral);
		free(status);
		free(ifaddr);
	}

	XCloseDisplay(dpy);

	return 0;
}
Ejemplo n.º 15
0
/* init phase :
 * 1) read configuration file
 * 2) read command line arguments
 * 3) daemonize
 * 4) check and write pid file
 * 5) set startup time stamp
 * 6) compute presentation URL
 * 7) set signal handlers */
static int
init(int argc, char * * argv)
{
	int i;
	int pid;
	int debug_flag = 0;
	int verbose_flag = 0;
	int options_flag = 0;
	struct sigaction sa;
	const char * presurl = NULL;
	const char * optionsfile = "/etc/minidlna.conf";
	char mac_str[13];
	char * string, * word;
	enum media_types type;
	char * path;
	char buf[PATH_MAX];
	char ip_addr[INET_ADDRSTRLEN + 3] = {'\0'};
	char log_str[72] = "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn";
	char *log_level = NULL;

	/* first check if "-f" option is used */
	for(i=2; i<argc; i++)
	{
		if(0 == strcmp(argv[i-1], "-f"))
		{
			optionsfile = argv[i];
			options_flag = 1;
			break;
		}
	}

	/* set up uuid based on mac address */
	if( getsyshwaddr(mac_str, sizeof(mac_str)) < 0 )
	{
		DPRINTF(E_OFF, L_GENERAL, "No MAC address found.  Falling back to generic UUID.\n");
		strcpy(mac_str, "554e4b4e4f57");
	}
	strcpy(uuidvalue+5, "4d696e69-444c-164e-9d41-");
	strncat(uuidvalue, mac_str, 12);

	getfriendlyname(friendly_name, FRIENDLYNAME_MAX_LEN);
	
	runtime_vars.port = -1;
	runtime_vars.notify_interval = 895;	/* seconds between SSDP announces */
	runtime_vars.root_container = NULL;

	/* read options file first since
	 * command line arguments have final say */
	if(readoptionsfile(optionsfile) < 0)
	{
		/* only error if file exists or using -f */
		if(access(optionsfile, F_OK) == 0 || options_flag)
			DPRINTF(E_ERROR, L_GENERAL, "Error reading configuration file %s\n", optionsfile);
	}
	else
	{
		for(i=0; i<num_options; i++)
		{
			switch(ary_options[i].id)
			{
			case UPNPIFNAME:
				for( string = ary_options[i].value; (word = strtok(string, ",")); string = NULL )
				{
					if(n_lan_addr < MAX_LAN_ADDR)
					{
						if(getifaddr(word, ip_addr, sizeof(ip_addr)) >= 0)
						{
							if( *ip_addr && parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0 )
								if(n_lan_addr < MAX_LAN_ADDR)
									n_lan_addr++;
						}
					}
					else
					{
						DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
				    		    MAX_LAN_ADDR, word);
					}
				}
				break;
			case UPNPLISTENING_IP:
				if(n_lan_addr < MAX_LAN_ADDR)
				{
					if(parselanaddr(&lan_addr[n_lan_addr],
					             ary_options[i].value) == 0)
						n_lan_addr++;
				}
				else
				{
					DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
			    		    MAX_LAN_ADDR, ary_options[i].value);
				}
				break;
			case UPNPPORT:
				runtime_vars.port = atoi(ary_options[i].value);
				break;
			case UPNPPRESENTATIONURL:
				presurl = ary_options[i].value;
				break;
			case UPNPNOTIFY_INTERVAL:
				runtime_vars.notify_interval = atoi(ary_options[i].value);
				break;
			case UPNPSERIAL:
				strncpyt(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
				break;				
			case UPNPMODEL_NAME:
				strncpyt(modelname, ary_options[i].value, MODELNAME_MAX_LEN);
				break;
			case UPNPMODEL_NUMBER:
				strncpyt(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
				break;
			case UPNPFRIENDLYNAME:
				strncpyt(friendly_name, ary_options[i].value, FRIENDLYNAME_MAX_LEN);
				break;
			case UPNPMEDIADIR:
				type = ALL_MEDIA;
				char * myval = NULL;
				switch( ary_options[i].value[0] )
				{
				case 'A':
				case 'a':
					if( ary_options[i].value[0] == 'A' || ary_options[i].value[0] == 'a' )
						type = AUDIO_ONLY;
				case 'V':
				case 'v':
					if( ary_options[i].value[0] == 'V' || ary_options[i].value[0] == 'v' )
						type = VIDEO_ONLY;
				case 'P':
				case 'p':
					if( ary_options[i].value[0] == 'P' || ary_options[i].value[0] == 'p' )
						type = IMAGES_ONLY;
					myval = index(ary_options[i].value, '/');
				case '/':
					path = realpath(myval ? myval:ary_options[i].value, buf);
					if( !path )
						path = (myval ? myval:ary_options[i].value);
					if( access(path, F_OK) != 0 )
					{
						DPRINTF(E_ERROR, L_GENERAL, "Media directory \"%s\" not accessible! [%s]\n",
						        path, strerror(errno));
						break;
					}
					struct media_dir_s * this_dir = calloc(1, sizeof(struct media_dir_s));
					this_dir->path = strdup(path);
					this_dir->type = type;
					if( !media_dirs )
					{
						media_dirs = this_dir;
					}
					else
					{
						struct media_dir_s * all_dirs = media_dirs;
						while( all_dirs->next )
							all_dirs = all_dirs->next;
						all_dirs->next = this_dir;
					}
					break;
				default:
					DPRINTF(E_ERROR, L_GENERAL, "Media directory entry not understood! [%s]\n",
					        ary_options[i].value);
					break;
				}
				break;
			case UPNPALBUMART_NAMES:
				for( string = ary_options[i].value; (word = strtok(string, "/")); string = NULL )
				{
					struct album_art_name_s * this_name = calloc(1, sizeof(struct album_art_name_s));
					int len = strlen(word);
					if( word[len-1] == '*' )
					{
						word[len-1] = '\0';
						this_name->wildcard = 1;
					}
					this_name->name = strdup(word);
					if( !album_art_names )
					{
						album_art_names = this_name;
					}
					else
					{
						struct album_art_name_s * all_names = album_art_names;
						while( all_names->next )
							all_names = all_names->next;
						all_names->next = this_name;
					}
				}
				break;
			case UPNPDBDIR:
				path = realpath(ary_options[i].value, buf);
				if( !path )
					path = (ary_options[i].value);
				make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
				if( access(path, F_OK) != 0 )
				{
					DPRINTF(E_FATAL, L_GENERAL, "Database path not accessible! [%s]\n", path);
					break;
				}
				strncpyt(db_path, path, PATH_MAX);
				break;
			case UPNPLOGDIR:
				path = realpath(ary_options[i].value, buf);
				if( !path )
					path = (ary_options[i].value);
				make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
				if( access(path, F_OK) != 0 )
				{
					DPRINTF(E_FATAL, L_GENERAL, "Log path not accessible! [%s]\n", path);
					break;
				}
				strncpyt(log_path, path, PATH_MAX);
				break;
			case UPNPLOGLEVEL:
				log_level = ary_options[i].value;
				break;
			case UPNPINOTIFY:
				if( (strcmp(ary_options[i].value, "yes") != 0) && !atoi(ary_options[i].value) )
					CLEARFLAG(INOTIFY_MASK);
				break;
			case ENABLE_TIVO:
				if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) )
					SETFLAG(TIVO_MASK);
				break;
			case ENABLE_DLNA_STRICT:
				if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) )
					SETFLAG(DLNA_STRICT_MASK);
				break;
			case ROOT_CONTAINER:
				switch( ary_options[i].value[0] )
				{
				case '.':
					runtime_vars.root_container = NULL;
					break;
				case 'B':
				case 'b':
					runtime_vars.root_container = BROWSEDIR_ID;
					break;
				case 'M':
				case 'm':
					runtime_vars.root_container = MUSIC_ID;
					break;
				case 'V':
				case 'v':
					runtime_vars.root_container = VIDEO_ID;
					break;
				case 'P':
				case 'p':
					runtime_vars.root_container = IMAGE_ID;
					break;
				default:
					DPRINTF(E_ERROR, L_GENERAL, "Invalid root container! [%s]\n",
						ary_options[i].value);
					break;
				}
				break;
			case UPNPMINISSDPDSOCKET:
				minissdpdsocketpath = ary_options[i].value;
				break;
			default:
				DPRINTF(E_ERROR, L_GENERAL, "Unknown option in file %s\n",
				        optionsfile);
			}
		}
	}
	if( log_path[0] == '\0' )
	{
		if( db_path[0] == '\0' )
			strncpyt(log_path, DEFAULT_LOG_PATH, PATH_MAX);
		else
			strncpyt(log_path, db_path, PATH_MAX);
	}
	if( db_path[0] == '\0' )
		strncpyt(db_path, DEFAULT_DB_PATH, PATH_MAX);

	/* command line arguments processing */
	for(i=1; i<argc; i++)
	{
		if(argv[i][0]!='-')
		{
			DPRINTF(E_ERROR, L_GENERAL, "Unknown option: %s\n", argv[i]);
		}
		else if(strcmp(argv[i], "--help")==0)
		{
			runtime_vars.port = 0;
			break;
		}
		else switch(argv[i][1])
		{
		case 't':
			if(i+1 < argc)
				runtime_vars.notify_interval = atoi(argv[++i]);
			else
				DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 's':
			if(i+1 < argc)
				strncpyt(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
			else
				DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'm':
			if(i+1 < argc)
				strncpyt(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
			else
				DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'p':
			if(i+1 < argc)
				runtime_vars.port = atoi(argv[++i]);
			else
				DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'P':
			if(i+1 < argc)
				pidfilename = argv[++i];
			else
				DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'd':
			debug_flag = 1;
		case 'v':
			verbose_flag = 1;
			break;
		case 'L':
			SETFLAG(NO_PLAYLIST_MASK);
			break;
		case 'w':
			if(i+1 < argc)
				presurl = argv[++i];
			else
				DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'a':
			if(i+1 < argc)
			{
				int address_already_there = 0;
				int j;
				i++;
				for(j=0; j<n_lan_addr; j++)
				{
					struct lan_addr_s tmpaddr;
					parselanaddr(&tmpaddr, argv[i]);
					if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
						address_already_there = 1;
				}
				if(address_already_there)
					break;
				if(n_lan_addr < MAX_LAN_ADDR)
				{
					if(parselanaddr(&lan_addr[n_lan_addr], argv[i]) == 0)
						n_lan_addr++;
				}
				else
				{
					DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
				    	    MAX_LAN_ADDR, argv[i]);
				}
			}
			else
				DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'i':
			if(i+1 < argc)
			{
				int address_already_there = 0;
				int j;
				i++;
				if( getifaddr(argv[i], ip_addr, sizeof(ip_addr)) < 0 )
				{
					DPRINTF(E_FATAL, L_GENERAL, "Required network interface '%s' not found.\n",
						argv[i]);
				}
				for(j=0; j<n_lan_addr; j++)
				{
					struct lan_addr_s tmpaddr;
					parselanaddr(&tmpaddr, ip_addr);
					if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
						address_already_there = 1;
				}
				if(address_already_there)
					break;
				if(n_lan_addr < MAX_LAN_ADDR)
				{
					if(parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0)
						n_lan_addr++;
				}
				else
				{
					DPRINTF(E_ERROR, L_GENERAL, "Too many listening ips (max: %d), ignoring %s\n",
				    	    MAX_LAN_ADDR, argv[i]);
				}
			}
			else
				DPRINTF(E_ERROR, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'f':
			i++;	/* discarding, the config file is already read */
			break;
		case 'h':
			runtime_vars.port = 0; // triggers help display
			break;
		case 'R':
			snprintf(buf, sizeof(buf), "rm -rf %s/files.db %s/art_cache", db_path, db_path);
			if( system(buf) != 0 )
				DPRINTF(E_WARN, L_GENERAL, "Failed to clean old file cache.\n");
			break;
		case 'V':
			printf("Version " MINIDLNA_VERSION "\n");
			exit(0);
			break;
		default:
			DPRINTF(E_ERROR, L_GENERAL, "Unknown option: %s\n", argv[i]);
		}
	}
	/* If no IP was specified, try to detect one */
	if( n_lan_addr < 1 )
	{
		if( (getsysaddr(ip_addr, sizeof(ip_addr)) < 0) &&
		    (getifaddr("eth0", ip_addr, sizeof(ip_addr)) < 0) &&
		    (getifaddr("eth1", ip_addr, sizeof(ip_addr)) < 0) )
		{
			DPRINTF(E_OFF, L_GENERAL, "No IP address automatically detected!\n");
		}
		if( *ip_addr && parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0 )
		{
			n_lan_addr++;
		}
	}

	if( (n_lan_addr==0) || (runtime_vars.port<=0) )
	{
		DPRINTF(E_ERROR, L_GENERAL, "Usage:\n\t"
		        "%s [-d] [-v] [-f config_file]\n"
			"\t\t[-a listening_ip] [-p port]\n"
			/*"[-l logfile] " not functionnal */
			"\t\t[-s serial] [-m model_number] \n"
			"\t\t[-t notify_interval] [-P pid_filename]\n"
			"\t\t[-w url] [-R] [-V] [-h]\n"
		        "\nNotes:\n\tNotify interval is in seconds. Default is 895 seconds.\n"
			"\tDefault pid file is %s.\n"
			"\tWith -d minidlna will run in debug mode (not daemonize).\n"
			"\t-w sets the presentation url. Default is http address on port 80\n"
			"\t-h displays this text\n"
			"\t-R forces a full rescan\n"
			"\t-L do note create playlists\n"
			"\t-V print the version number\n",
		        argv[0], pidfilename);
		return 1;
	}

	if( verbose_flag )
	{
		strcpy(log_str+65, "debug");
		log_level = log_str;
	}
	else if( !log_level )
	{
		log_level = log_str;
	}
	if(debug_flag)
	{
		pid = getpid();
		log_init(NULL, log_level);
	}
	else
	{
		pid = daemonize();
		#ifdef READYNAS
		log_init("/var/log/upnp-av.log", log_level);
		#else
		if( access(db_path, F_OK) != 0 )
			make_dir(db_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
		sprintf(buf, "%s/minidlna.log", log_path);
		log_init(buf, log_level);
		#endif
	}

	if(checkforrunning(pidfilename) < 0)
	{
		DPRINTF(E_ERROR, L_GENERAL, "MiniDLNA is already running. EXITING.\n");
		return 1;
	}	

	set_startup_time();

	/* presentation url */
	if(presurl)
		strncpyt(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
	else
		strcpy(presentationurl, "/");

	/* set signal handler */
	memset(&sa, 0, sizeof(struct sigaction));
	sa.sa_handler = sigterm;
	if (sigaction(SIGTERM, &sa, NULL))
	{
		DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGTERM handler. EXITING.\n");
	}
	if (sigaction(SIGINT, &sa, NULL))
	{
		DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGINT handler. EXITING.\n");
	}

	if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
		DPRINTF(E_FATAL, L_GENERAL, "Failed to ignore SIGPIPE signals. EXITING.\n");
	}

	writepidfile(pidfilename, pid);

	return 0;
}
Ejemplo n.º 16
0
int getifaddr_in6(const char * ifname, int af, struct in6_addr * addr)
{
#if defined(ENABLE_IPV6) || defined(USE_GETIFADDRS)
	struct ifaddrs * ifap;
	struct ifaddrs * ife;
#ifdef ENABLE_IPV6
	const struct sockaddr_in6 * tmpaddr;
#endif /* ENABLE_IPV6 */
	int found = 0;

	if(!ifname || ifname[0]=='\0')
		return -1;
	if(getifaddrs(&ifap)<0)
	{
		syslog(LOG_ERR, "getifaddrs: %m");
		return -1;
	}
	for(ife = ifap; ife && !found; ife = ife->ifa_next)
	{
		/* skip other interfaces if one was specified */
		if(ifname && (0 != strcmp(ifname, ife->ifa_name)))
			continue;
		if(ife->ifa_addr == NULL)
			continue;
		if (ife->ifa_addr->sa_family != af)
			continue;
		switch(ife->ifa_addr->sa_family)
		{
		case AF_INET:
			/* IPv4-mapped IPv6 address ::ffff:1.2.3.4 */
			memset(addr->s6_addr, 0, 10);
			addr->s6_addr[10] = 0xff;
			addr->s6_addr[11] = 0xff;
			memcpy(addr->s6_addr + 12,
			       &(((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr),
			       4);
			found = 1;
			break;

#ifdef ENABLE_IPV6
		case AF_INET6:
			tmpaddr = (const struct sockaddr_in6 *)ife->ifa_addr;
			if(!IN6_IS_ADDR_LOOPBACK(&tmpaddr->sin6_addr)
			   && !IN6_IS_ADDR_LINKLOCAL(&tmpaddr->sin6_addr))
			{
				memcpy(addr->s6_addr,
				       &tmpaddr->sin6_addr,
				       16);
				found = 1;
			}
			break;
#endif /* ENABLE_IPV6 */
		}
	}
	freeifaddrs(ifap);
	return (found ? 0 : -1);
#else /* defined(ENABLE_IPV6) || defined(USE_GETIFADDRS) */
	/* IPv4 only */
	struct in_addr addr4;
	if(af != AF_INET)
		return -1;
	if(getifaddr(ifname, NULL, 0, &addr4, NULL) < 0)
		return -1;
	/* IPv4-mapped IPv6 address ::ffff:1.2.3.4 */
	memset(addr->s6_addr, 0, 10);
	addr->s6_addr[10] = 0xff;
	addr->s6_addr[11] = 0xff;
	memcpy(addr->s6_addr + 12, &addr4.s_addr, 4);
	return 0;
#endif
}
Ejemplo n.º 17
0
/* init phase :
 * 1) read configuration file
 * 2) read command line arguments
 * 3) daemonize
 * 4) check and write pid file
 * 5) set startup time stamp
 * 6) set signal handlers */
static int
init(int argc, char * * argv)
{
	int i;
	int pid;
	int debug_flag = 0;
	int options_flag = 0;
	struct sigaction sa;
	/*const char * logfilename = 0;*/
	const char * presurl = 0;
	const char * optionsfile = "/etc/dlnaproxy.conf";
	char mac_str[13];
	char * string, * word;
	char * path;
	char real_path[PATH_MAX];
	char ip_addr[INET_ADDRSTRLEN + 3] = {'\0'};

	/* first check if "-f" option is used */
	for(i=2; i<argc; i++)
	{
		if(0 == strcmp(argv[i-1], "-f"))
		{
			optionsfile = argv[i];
			options_flag = 1;
			break;
		}
	}

	/* set up uuid based on mac address */
	if( getsyshwaddr(mac_str, sizeof(mac_str)) < 0 )
	{
		DPRINTF(E_OFF, L_GENERAL, "No MAC address found.  Falling back to generic UUID.\n");
		strcpy(mac_str, "554e4b4e4f57");
	}
	strcpy(uuidvalue+5, "4d696e69-444c-164e-9d41-");
	strncat(uuidvalue, mac_str, 12);

	getfriendlyname(friendly_name, FRIENDLYNAME_MAX_LEN);
	
	runtime_vars.port = -1;
	runtime_vars.notify_interval = 895;	/* seconds between SSDP announces */
	runtime_vars.rport = 50001;
	runtime_vars.rhost = "192.168.1.1";

	/* read options file first since
	 * command line arguments have final say */
	if(readoptionsfile(optionsfile) < 0)
	{
		/* only error if file exists or using -f */
		if(access(optionsfile, F_OK) == 0 || options_flag)
			fprintf(stderr, "Error reading configuration file %s\n", optionsfile);
	}
	else
	{
		for(i=0; i<num_options; i++)
		{
			switch(ary_options[i].id)
			{
			case UPNPIFNAME:
				for( string = ary_options[i].value; (word = strtok(string, ",")); string = NULL )
				{
					if(n_lan_addr < MAX_LAN_ADDR)
					{
						if(getifaddr(word, ip_addr, sizeof(ip_addr)) >= 0)
						{
							if( *ip_addr && parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0 )
								if(n_lan_addr < MAX_LAN_ADDR)
									n_lan_addr++;
						}
						else
							fprintf(stderr, "Interface %s not found, ignoring.\n", word);
					}
					else
					{
						fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n",
				    		    MAX_LAN_ADDR, word);
					}
				}
				break;
			case UPNPLISTENING_IP:
				if(n_lan_addr < MAX_LAN_ADDR)
				{
					if(parselanaddr(&lan_addr[n_lan_addr],
					             ary_options[i].value) == 0)
						n_lan_addr++;
				}
				else
				{
					fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n",
			    		    MAX_LAN_ADDR, ary_options[i].value);
				}
				break;
			case UPNPPORT:
				runtime_vars.port = atoi(ary_options[i].value);
				break;
			case UPNPNOTIFY_INTERVAL:
				runtime_vars.notify_interval = atoi(ary_options[i].value);
				break;
			case UPNPSERIAL:
				strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
				serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
				break;				
			case UPNPMODEL_NAME:
				strncpy(modelname, ary_options[i].value, MODELNAME_MAX_LEN);
				modelname[MODELNAME_MAX_LEN-1] = '\0';
				break;
			case UPNPMODEL_NUMBER:
				strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
				modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
				break;
			case UPNPLOGDIR:
				path = realpath(ary_options[i].value, real_path);
				if( !path )
					path = (ary_options[i].value);
				make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
				if( access(path, F_OK) != 0 )
				{
					DPRINTF(E_FATAL, L_GENERAL, "Log path not accessible! [%s]\n", path);
					break;
				}
				strncpy(log_path, path, PATH_MAX);
				break;
			case UPNPMINISSDPDSOCKET:
				minissdpdsocketpath = ary_options[i].value;
				break;
			case UPNPREMOTEUUID:
				runtime_vars.ruuid = ary_options[i].value;
				strcpy(uuidvalue+5, runtime_vars.ruuid);
				break;
			case UPNPREMOTEPORT:
				runtime_vars.rport = atoi(ary_options[i].value);
				break;
			case UPNPREMOTEHOST:
				runtime_vars.rhost = ary_options[i].value;
				break;
			case UPNPDESCPATH:
				runtime_vars.path = ary_options[i].value;
				break;
			default:
				fprintf(stderr, "Unknown option with value %s in file %s\n",
				        ary_options[i].value, optionsfile);
			}
		}
	}
	if( log_path[0] == '\0' )
	{
		strncpy(log_path, DEFAULT_LOG_PATH, PATH_MAX);
	}

	/* command line arguments processing */
	for(i=1; i<argc; i++)
	{
		if(argv[i][0]!='-')
		{
			fprintf(stderr, "Unknown option: %s\n", argv[i]);
		}
		else if(strcmp(argv[i], "--help")==0)
		{
			runtime_vars.port = 0;
			break;
		}
		else switch(argv[i][1])
		{
		case 't':
			if(i+1 < argc)
				runtime_vars.notify_interval = atoi(argv[++i]);
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		/*case 'l':
			logfilename = argv[++i];
			break;*/
		case 'p':
			if(i+1 < argc)
				runtime_vars.port = atoi(argv[++i]);
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'P':
			if(i+1 < argc)
				pidfilename = argv[++i];
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'd':
			debug_flag = 1;
			break;
		case 'a':
			if(i+1 < argc)
			{
				int address_already_there = 0;
				int j;
				i++;
				for(j=0; j<n_lan_addr; j++)
				{
					struct lan_addr_s tmpaddr;
					parselanaddr(&tmpaddr, argv[i]);
					if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
						address_already_there = 1;
				}
				if(address_already_there)
					break;
				if(n_lan_addr < MAX_LAN_ADDR)
				{
					if(parselanaddr(&lan_addr[n_lan_addr], argv[i]) == 0)
						n_lan_addr++;
				}
				else
				{
					fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n",
				    	    MAX_LAN_ADDR, argv[i]);
				}
			}
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'i':
			if(i+1 < argc)
			{
				int address_already_there = 0;
				int j;
				i++;
				if( getifaddr(argv[i], ip_addr, sizeof(ip_addr)) < 0 )
				{
					fprintf(stderr, "Network interface '%s' not found.\n",
						argv[i]);
					exit(-1);
				}
				for(j=0; j<n_lan_addr; j++)
				{
					struct lan_addr_s tmpaddr;
					parselanaddr(&tmpaddr, ip_addr);
					if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
						address_already_there = 1;
				}
				if(address_already_there)
					break;
				if(n_lan_addr < MAX_LAN_ADDR)
				{
					if(parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0)
						n_lan_addr++;
				}
				else
				{
					fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n",
				    	    MAX_LAN_ADDR, argv[i]);
				}
			}
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'f':
			i++;	/* discarding, the config file is already read */
			break;
		case 'h':
			runtime_vars.port = 0; // triggers help display
			break;
		case 'V':
			printf("Version " DLNAPROXY_VERSION "\n");
			exit(0);
			break;
		default:
			fprintf(stderr, "Unknown option: %s\n", argv[i]);
		}
	}
	/* If no IP was specified, try to detect one */
	if( n_lan_addr < 1 )
	{
		if( (getsysaddr(ip_addr, sizeof(ip_addr)) < 0) &&
		    (getifaddr("eth0", ip_addr, sizeof(ip_addr)) < 0) &&
		    (getifaddr("eth1", ip_addr, sizeof(ip_addr)) < 0) )
		{
			DPRINTF(E_OFF, L_GENERAL, "No IP address automatically detected!\n");
		}
		if( *ip_addr && parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0 )
		{
			n_lan_addr++;
		}
	}

	if( (n_lan_addr==0) || (runtime_vars.port<=0) )
	{
		fprintf(stderr, "Usage:\n\t"
		        "%s [-d] [-f config_file]\n"
			"\t\t[-a listening_ip] [-p port]\n"
			/*"[-l logfile] " not functionnal */
			"\t\t[-t notify_interval] [-P pid_filename]\n"
			"\t\t[-V] [-h]\n"
		        "\nNotes:\n\tNotify interval is in seconds. Default is 895 seconds.\n"
			"\tDefault pid file is %s.\n"
			"\tWith -d dlnaproxy will run in debug mode (not daemonize).\n"
			"\t-h displays this text\n"
			"\t-V print the version number\n",
		        argv[0], pidfilename);
		return 1;
	}

	if(debug_flag)
	{
		pid = getpid();
		log_init(NULL, "general,inotify,http,ssdp=debug");
	}
	else
	{
#ifdef USE_DAEMON
		if(daemon(0, 0)<0) {
			perror("daemon()");
		}
		pid = getpid();
#else
		pid = daemonize();
#endif
		if( access(log_path, F_OK) != 0 )
			make_dir(log_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
		sprintf(real_path, "%s/dlnaproxy.log", log_path);
		log_init(real_path, "general,inotify,http,ssdp=warn");
	}

	if(checkforrunning(pidfilename) < 0)
	{
		DPRINTF(E_ERROR, L_GENERAL, "DLNAProxy is already running. EXITING.\n");
		return 1;
	}	

	set_startup_time();

	/* presentation url */
	if(presurl)
	{
		strncpy(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
		presentationurl[PRESENTATIONURL_MAX_LEN-1] = '\0';
	}
	else
	{
		snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
		         "http://%s:%d/", lan_addr[0].str, runtime_vars.port);
	}

	/* set signal handler */
	signal(SIGCLD, SIG_IGN);
	memset(&sa, 0, sizeof(struct sigaction));
	sa.sa_handler = sigterm;
	if (sigaction(SIGTERM, &sa, NULL))
	{
		DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGTERM handler. EXITING.\n");
	}
	if (sigaction(SIGINT, &sa, NULL))
	{
		DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGINT handler. EXITING.\n");
	}

	if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
		DPRINTF(E_FATAL, L_GENERAL, "Failed to ignore SIGPIPE signals. EXITING.\n");
	}

	writepidfile(pidfilename, pid);

	return 0;
}
Ejemplo n.º 18
0
/* init phase :
 * 1) read configuration file
 * 2) read command line arguments
 * 3) daemonize
 * 4) check and write pid file
 * 5) set startup time stamp
 * 6) compute presentation URL
 * 7) set signal handlers */
static int
init(int argc, char * * argv)
{
	int i;
	int pid;
	int debug_flag = 0;
	int options_flag = 0;
	struct sigaction sa;
	/*const char * logfilename = 0;*/
	const char * presurl = 0;
#if 1
	const char * optionsfile = "/system/etc/minidlna.conf";
#else
	const char * optionsfile = "/etc/minidlna.conf";
#endif
	char mac_str[13];
	char * string, * word;
	enum media_types type;
	char * path;
	char real_path[PATH_MAX];
	char ext_ip_addr[INET_ADDRSTRLEN] = {'\0'};

	/* first check if "-f" option is used */
	for(i=2; i<argc; i++)
	{
		if(0 == strcmp(argv[i-1], "-f"))
		{
			optionsfile = argv[i];
			options_flag = 1;
			break;
		}
	}

	/* set up uuid based on mac address */
	if( getsyshwaddr(mac_str, sizeof(mac_str)) < 0 )
	{
		DPRINTF(E_OFF, L_GENERAL, "No MAC address found.  Falling back to generic UUID.\n");
		strcpy(mac_str, "554e4b4e4f57");
	}
	strcpy(uuidvalue+5, "4d696e69-444c-164e-9d41-");
	strncat(uuidvalue, mac_str, 12);

	getfriendlyname(friendly_name, FRIENDLYNAME_MAX_LEN);
	
	runtime_vars.port = -1;
	runtime_vars.notify_interval = 895;	/* seconds between SSDP announces */

	/* read options file first since
	 * command line arguments have final say */
	if(readoptionsfile(optionsfile) < 0)
	{
		/* only error if file exists or using -f */
		if(access(optionsfile, F_OK) == 0 || options_flag)
			fprintf(stderr, "Error reading configuration file %s\n", optionsfile);
	}
	else
	{
		for(i=0; i<num_options; i++)
		{
			switch(ary_options[i].id)
			{
			case UPNPIFNAME:
				if(getifaddr(ary_options[i].value, ext_ip_addr, INET_ADDRSTRLEN) >= 0)
				{
					if( *ext_ip_addr && parselanaddr(&lan_addr[n_lan_addr], ext_ip_addr) == 0 )
						n_lan_addr++;
				}
				else
					fprintf(stderr, "Interface %s not found, ignoring.\n", ary_options[i].value);
				break;
			case UPNPLISTENING_IP:
				if(n_lan_addr < MAX_LAN_ADDR)
				{
					if(parselanaddr(&lan_addr[n_lan_addr],
					             ary_options[i].value) == 0)
						n_lan_addr++;
				}
				else
				{
					fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n",
			    		    MAX_LAN_ADDR, ary_options[i].value);
				}
				break;
			case UPNPPORT:
				runtime_vars.port = atoi(ary_options[i].value);
				break;
			case UPNPPRESENTATIONURL:
				presurl = ary_options[i].value;
				break;
			case UPNPNOTIFY_INTERVAL:
				runtime_vars.notify_interval = atoi(ary_options[i].value);
				break;
			case UPNPSERIAL:
				strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
				serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
				break;				
			case UPNPMODEL_NUMBER:
				strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
				modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
				break;
			case UPNPFRIENDLYNAME:
				strncpy(friendly_name, ary_options[i].value, FRIENDLYNAME_MAX_LEN);
				friendly_name[FRIENDLYNAME_MAX_LEN-1] = '\0';
				break;
			case UPNPMEDIADIR:
				type = ALL_MEDIA;
				char * myval = NULL;
				switch( ary_options[i].value[0] )
				{
				case 'A':
				case 'a':
					if( ary_options[i].value[0] == 'A' || ary_options[i].value[0] == 'a' )
						type = AUDIO_ONLY;
				case 'V':
				case 'v':
					if( ary_options[i].value[0] == 'V' || ary_options[i].value[0] == 'v' )
						type = VIDEO_ONLY;
				case 'P':
				case 'p':
					if( ary_options[i].value[0] == 'P' || ary_options[i].value[0] == 'p' )
						type = IMAGES_ONLY;
					myval = index(ary_options[i].value, '/');
				case '/':
					path = realpath(myval ? myval:ary_options[i].value, real_path);
					if( !path )
						path = (myval ? myval:ary_options[i].value);
					if( access(path, F_OK) != 0 )
					{
						fprintf(stderr, "Media directory not accessible! [%s]\n",
						        path);
						break;
					}
					struct media_dir_s * this_dir = calloc(1, sizeof(struct media_dir_s));
					this_dir->path = strdup(path);
					this_dir->type = type;
					if( !media_dirs )
					{
						media_dirs = this_dir;
					}
					else
					{
						struct media_dir_s * all_dirs = media_dirs;
						while( all_dirs->next )
							all_dirs = all_dirs->next;
						all_dirs->next = this_dir;
					}
					break;
				default:
					fprintf(stderr, "Media directory entry not understood! [%s]\n",
					        ary_options[i].value);
					break;
				}
				break;
			case UPNPALBUMART_NAMES:
				for( string = ary_options[i].value; (word = strtok(string, "/")); string = NULL ) {
					struct album_art_name_s * this_name = calloc(1, sizeof(struct album_art_name_s));
					this_name->name = strdup(word);
					if( !album_art_names )
					{
						album_art_names = this_name;
					}
					else
					{
						struct album_art_name_s * all_names = album_art_names;
						while( all_names->next )
							all_names = all_names->next;
						all_names->next = this_name;
					}
				}
				break;
			case UPNPINOTIFY:
				if( (strcmp(ary_options[i].value, "yes") != 0) && !atoi(ary_options[i].value) )
					CLEARFLAG(INOTIFY_MASK);
				break;
			case ENABLE_TIVO:
				if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) )
					SETFLAG(TIVO_MASK);
				break;
			case ENABLE_DLNA_STRICT:
				if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) )
					SETFLAG(DLNA_STRICT_MASK);
				break;
			default:
				fprintf(stderr, "Unknown option in file %s\n",
				        optionsfile);
			}
		}
	}

	/* command line arguments processing */
	for(i=1; i<argc; i++)
	{
		if(argv[i][0]!='-')
		{
			fprintf(stderr, "Unknown option: %s\n", argv[i]);
		}
		else if(strcmp(argv[i], "--help")==0)
		{
			runtime_vars.port = 0;
			break;
		}
		else switch(argv[i][1])
		{
		case 't':
			if(i+1 < argc)
				runtime_vars.notify_interval = atoi(argv[++i]);
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 's':
			if(i+1 < argc)
				strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
			break;
		case 'm':
			if(i+1 < argc)
				strncpy(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
			break;
		/*case 'l':
			logfilename = argv[++i];
			break;*/
		case 'p':
			if(i+1 < argc)
				runtime_vars.port = atoi(argv[++i]);
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'P':
			if(i+1 < argc)
				pidfilename = argv[++i];
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'd':
			debug_flag = 1;
			break;
		case 'w':
			if(i+1 < argc)
				presurl = argv[++i];
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'a':
			if(i+1 < argc)
			{
				int address_already_there = 0;
				int j;
				i++;
				for(j=0; j<n_lan_addr; j++)
				{
					struct lan_addr_s tmpaddr;
					parselanaddr(&tmpaddr, argv[i]);
					if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
						address_already_there = 1;
				}
				if(address_already_there)
					break;
				if(n_lan_addr < MAX_LAN_ADDR)
				{
					if(parselanaddr(&lan_addr[n_lan_addr], argv[i]) == 0)
						n_lan_addr++;
				}
				else
				{
					fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n",
				    	    MAX_LAN_ADDR, argv[i]);
				}
			}
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'i':
			if(i+1 < argc)
			{
				int address_already_there = 0;
				int j;
				i++;
				if( getifaddr(argv[i], ext_ip_addr, INET_ADDRSTRLEN) < 0 )
				{
					fprintf(stderr, "Network interface '%s' not found.\n",
						argv[i]);
					exit(-1);
				}
				for(j=0; j<n_lan_addr; j++)
				{
					struct lan_addr_s tmpaddr;
					parselanaddr(&tmpaddr, ext_ip_addr);
					if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
						address_already_there = 1;
				}
				if(address_already_there)
					break;
				if(n_lan_addr < MAX_LAN_ADDR)
				{
					if(parselanaddr(&lan_addr[n_lan_addr], ext_ip_addr) == 0)
						n_lan_addr++;
				}
				else
				{
					fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n",
				    	    MAX_LAN_ADDR, argv[i]);
				}
			}
			else
				fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
			break;
		case 'f':
			i++;	/* discarding, the config file is already read */
			break;
		case 'h':
			runtime_vars.port = 0; // triggers help display
			break;
		case 'R':
			system("rm -rf " DB_PATH); // triggers a full rescan
			break;
		case 'V':
			printf("Version " MINIDLNA_VERSION "\n");
			exit(0);
			break;
		default:
			fprintf(stderr, "Unknown option: %s\n", argv[i]);
		}
	}
	/* If no IP was specified, try to detect one */
	if( n_lan_addr < 1 )
	{
		if( (getsysaddr(ext_ip_addr, INET_ADDRSTRLEN) < 0) &&
		    (getifaddr("eth0", ext_ip_addr, INET_ADDRSTRLEN) < 0) &&
		    (getifaddr("eth1", ext_ip_addr, INET_ADDRSTRLEN) < 0) )
		{
			DPRINTF(E_OFF, L_GENERAL, "No IP address automatically detected!\n");
		}
		if( *ext_ip_addr && parselanaddr(&lan_addr[n_lan_addr], ext_ip_addr) == 0 )
		{
			n_lan_addr++;
		}
	}

	if( (n_lan_addr==0) || (runtime_vars.port<=0) )
	{
		fprintf(stderr, "Usage:\n\t"
		        "%s [-d] [-f config_file]\n"
			"\t\t[-a listening_ip] [-p port]\n"
			/*"[-l logfile] " not functionnal */
			"\t\t[-s serial] [-m model_number] \n"
			"\t\t[-t notify_interval] [-P pid_filename]\n"
			"\t\t[-w url] [-R] [-V] [-h]\n"
		        "\nNotes:\n\tNotify interval is in seconds. Default is 895 seconds.\n"
			"\tDefault pid file is %s.\n"
			"\tWith -d minidlna will run in debug mode (not daemonize).\n"
			"\t-w sets the presentation url. Default is http address on port 80\n"
			"\t-h displays this text\n"
			"\t-R forces a full rescan\n"
			"\t-V print the version number\n",
		        argv[0], pidfilename);
		return 1;
	}

	if(debug_flag)
	{
		pid = getpid();
		log_init(NULL, "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=debug");
	}
	else
	{
#ifdef USE_DAEMON
		if(daemon(0, 0)<0) {
			perror("daemon()");
		}
		pid = getpid();
#else
		pid = daemonize();
#endif
		#ifdef READYNAS
		log_init("/var/log/upnp-av.log", "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn");
		#else
		log_init(DB_PATH "/minidlna.log", "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn");
		#endif
	}

	if(checkforrunning(pidfilename) < 0)
	{
		DPRINTF(E_ERROR, L_GENERAL, "MiniDLNA is already running. EXITING.\n");
		return 1;
	}	

	set_startup_time();

	/* presentation url */
	if(presurl)
	{
		strncpy(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
		presentationurl[PRESENTATIONURL_MAX_LEN-1] = '\0';
	}
	else
	{
#ifdef READYNAS
		snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
		         "https://%s/admin/", lan_addr[0].str);
#else
		snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
		         "http://%s:%d/", lan_addr[0].str, runtime_vars.port);
#endif
	}

	/* set signal handler */
	//signal(SIGCLD, SIG_IGN);
	signal(SIGCHLD, SIG_IGN);
	memset(&sa, 0, sizeof(struct sigaction));
	sa.sa_handler = sigterm;
	if (sigaction(SIGTERM, &sa, NULL))
	{
		DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGTERM handler. EXITING.\n");
	}
	if (sigaction(SIGINT, &sa, NULL))
	{
		DPRINTF(E_FATAL, L_GENERAL, "Failed to set SIGINT handler. EXITING.\n");
	}

	if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
		DPRINTF(E_FATAL, L_GENERAL, "Failed to ignore SIGPIPE signals. EXITING.\n");
	}

	writepidfile(pidfilename, pid);

	return 0;
}
Ejemplo n.º 19
0
/* disabled at the moment */
int
ProcessInterfaceUp(struct ifinfomsg *ifi)
{
	struct lan_iface_s * lan_iface;
	struct lan_iface_s * lan_iface2;
	struct lan_addr_s * lan_addr;
	char ifname[IFNAMSIZ];
	char ifstraddr[16];
	struct in_addr ifaddr;

	/* check if we already have this iface */
	for(lan_iface = lan_ifaces.lh_first; lan_iface != NULL; lan_iface = lan_iface->list.le_next)
		if (lan_iface->iface.index == ifi->ifi_index)
			break;

	if (lan_iface != NULL)
		return 0;

	if (if_indextoname(ifi->ifi_index, ifname) == NULL)
	{
		syslog(LOG_ERR, "if_indextoname(%d, ifname) failed", ifi->ifi_index);
		return -1;
	}

	if (getifaddr(ifname, ifstraddr, 16) < 0)
	{
		syslog(LOG_DEBUG, "getifaddr(%s, ifaddr, 16) failed", ifname);
		return 1;
	}

	if (inet_pton(AF_INET, ifstraddr, &ifaddr) != 1)
	{
		syslog(LOG_ERR, "inet_pton(AF_INET, \"%s\", &ifaddr) failed", ifstraddr);
		return -1;
	}

	/* check if this new interface has address which we need to listen to */
	for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
	{
		if (lan_addr->addr.s_addr != ifaddr.s_addr)
			continue;

		syslog(LOG_INFO, "Interface up: %s (%s)", ifname, ifstraddr);

		/* adding new lan_iface entry */
		lan_iface = (struct lan_iface_s *) malloc(sizeof(struct lan_iface_s));
		if (lan_iface == NULL)
		{
			syslog(LOG_ERR, "malloc(sizeof(struct lan_iface_s): %m");
			continue;
		}

		lan_iface->lan_addr = lan_addr;
		strncpy(lan_iface->iface.name, ifname, IFNAMSIZ);
		lan_iface->iface.index = ifi->ifi_index;
		lan_iface->iface.addr = ifaddr;
		lan_iface->snotify = -1;
#ifdef ENABLE_NATPMP
		lan_iface->snatpmp = -1;
#endif

		LIST_INSERT_HEAD(&lan_ifaces, lan_iface, list);

		/* adding multicast membership for SSDP */
		if(AddMulticastMembership(sudp, ifaddr.s_addr, ifi->ifi_index) < 0)
			syslog(LOG_WARNING, "Failed to add multicast membership for interface %s (%s)", ifname, ifstraddr);
		else
			syslog(LOG_INFO, "Multicast membership added for %s (%s)", ifname, ifstraddr);

		/* create SSDP notify socket */
		if (OpenAndConfSSDPNotifySocket(lan_iface) < 0)
			syslog(LOG_WARNING, "Failed to open SSDP notify socket for interface %s (%s)", ifname, ifstraddr);

#ifdef ENABLE_NATPMP
		/* create NAT-PMP socket */
		for(lan_iface2 = lan_ifaces.lh_first; lan_iface2 != NULL; lan_iface2 = lan_iface2->list.le_next)
			if (lan_iface2->lan_addr->addr.s_addr == lan_iface->lan_addr->addr.s_addr &&
			    lan_iface2->snatpmp >= 0)
				lan_iface->snatpmp = lan_iface2->snatpmp;

		if (lan_iface->snatpmp < 0)
		{
			lan_iface->snatpmp = OpenAndConfNATPMPSocket(ifaddr.s_addr);
			if (lan_iface->snatpmp < 0)
				syslog(LOG_ERR, "OpenAndConfNATPMPSocket(ifaddr.s_addr) failed for %s (%s)", ifname, ifstraddr);
			else
				syslog(LOG_INFO, "Listening for NAT-PMP connection on %s:%d", ifstraddr, NATPMP_PORT);
		}
#endif
	}

	return 0;
}
Ejemplo n.º 20
0
int
port_in_use(const char *if_name,
            unsigned eport, int proto,
            const char *iaddr, unsigned iport)
{
	int found = 0;
	char ip_addr_str[INET_ADDRSTRLEN];
	struct in_addr ip_addr;
#ifdef __linux__
	/* linux code */
	char line[256];
	FILE *f;
	const char * tcpfile = "/proc/net/tcp";
	const char * udpfile = "/proc/net/udp";
#endif

	if(getifaddr(if_name, ip_addr_str, INET_ADDRSTRLEN, &ip_addr, NULL) < 0) {
		ip_addr.s_addr = 0;
		ip_addr_str[0] = '\0';
	}

	syslog(LOG_DEBUG, "Check protocol %s for port %d on ext_if %s %s, %08X",
	    (proto==IPPROTO_TCP)?"tcp":"udp", eport, if_name,
	    ip_addr_str, (unsigned)ip_addr.s_addr);

	/* Phase 1 : check for local sockets (would be listed by netstat) */
#if defined(__linux__)
	f = fopen((proto==IPPROTO_TCP)?tcpfile:udpfile, "r");
	if (!f) {
		syslog(LOG_ERR, "cannot open %s", (proto==IPPROTO_TCP)?tcpfile:udpfile);
		return -1;
	}

	while (fgets(line, 255, f)) {
		char eaddr[68];
		unsigned tmp_port;
		if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
				"%*x:%*x %*x %*d %*d %*llu",
				eaddr, &tmp_port) == 2
		) {
			/* TODO add IPV6 support if enabled
			 * Presently assumes IPV4 */
#ifdef DEBUG
			syslog(LOG_DEBUG, "port_in_use check port %d and address %s", tmp_port, eaddr);
#endif
			if (tmp_port == eport) {
				char tmp_addr[4];
				struct in_addr *tmp_ip_addr = (struct in_addr *)tmp_addr;
				if (sscanf(eaddr,"%2hhx%2hhx%2hhx%2hhx",
					&tmp_addr[3],&tmp_addr[2],&tmp_addr[1],&tmp_addr[0]) == 4)
				{
					if (tmp_ip_addr->s_addr == 0 || tmp_ip_addr->s_addr == ip_addr.s_addr)
					{
						found++;
						break;  /* don't care how many, just that we found at least one */
					}
				}
			}
		}
	}
	fclose(f);

#elif defined(__OpenBSD__)
static struct nlist list[] = {
#if 0
        {"_tcpstat", 0, 0, 0, 0},
        {"_udpstat", 0, 0, 0, 0},
        {"_tcbinfo", 0, 0, 0, 0},
        {"_udbinfo", 0, 0, 0, 0},
#endif
		{"_tcbtable", 0, 0, 0, 0},
		{"_udbtable", 0, 0, 0, 0},
        {NULL,0, 0, 0, 0}
};
	char errstr[_POSIX2_LINE_MAX];
	kvm_t *kd;
	ssize_t n;
	struct inpcbtable table;
	struct inpcb *next;
	struct inpcb inpcb;
	kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errstr);
	if(!kd) {
		syslog(LOG_ERR, "%s: kvm_openfiles(): %s",
		       "portinuse()", errstr);
		return -1;
	}
	if(kvm_nlist(kd, list) < 0) {
		syslog(LOG_ERR, "%s: kvm_nlist(): %s",
		       "portinuse()", kvm_geterr(kd));
		kvm_close(kd);
		return -1;
	}
	n = kvm_read(kd, list[(proto==IPPROTO_TCP)?0:1].n_value, &table, sizeof(table));
	if(n < 0) {
		syslog(LOG_ERR, "%s: kvm_read(): %s",
		       "portinuse()", kvm_geterr(kd));
		kvm_close(kd);
		return -1;
	}
	next = CIRCLEQ_FIRST(&table.inpt_queue); /*TAILQ_FIRST(&table.inpt_queue);*/
	while(next != NULL) {
		if(((u_long)next & 3) != 0) break;
		n = kvm_read(kd, (u_long)next, &inpcb, sizeof(inpcb));
		if(n < 0) {
			syslog(LOG_ERR, "kvm_read(): %s", kvm_geterr(kd));
			break;
		}
		next = CIRCLEQ_NEXT(&inpcb, inp_queue);	/*TAILQ_NEXT(&inpcb, inp_queue);*/
		/* skip IPv6 sockets */
		if((inpcb.inp_flags & INP_IPV6) != 0)
			continue;
#ifdef DEBUG
		syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu",
		       (u_long)inpcb.inp_laddr.s_addr, ntohs(inpcb.inp_lport),
		       (u_long)inpcb.inp_faddr.s_addr, ntohs(inpcb.inp_fport));
#endif
		if(eport == (unsigned)ntohs(inpcb.inp_lport)) {
			if(inpcb.inp_laddr.s_addr == INADDR_ANY || inpcb.inp_laddr.s_addr == ip_addr.s_addr) {
				found++;
				break;  /* don't care how many, just that we found at least one */
			}
		}
	}
	kvm_close(kd);

#elif defined(__DragonFly__)
	const char *varname;
	struct xinpcb *xip;
	struct xtcpcb *xtp;
	struct inpcb *inp;
	void *buf = NULL;
	void *so_begin, *so_end;

	size_t len;

	switch (proto) {
	case IPPROTO_TCP:
		varname = "net.inet.tcp.pcblist";
		break;
	case IPPROTO_UDP:
		varname = "net.inet.udp.pcblist";
		break;
	default:
		syslog(LOG_ERR, "port_in_use() unknown proto=%d", proto);
		return -1;
	}

	if (sysctlbyname(varname, NULL, &len, NULL, 0) < 0) {
		syslog(LOG_ERR, "sysctlbyname(%s, NULL, ...): %m", varname);
		return -1;
	}
	buf = malloc(len);
	if (buf == NULL) {
		syslog(LOG_ERR, "malloc(%u) failed", (unsigned)len);
		return -1;
	}
	if (sysctlbyname(varname, buf, &len, NULL, 0) < 0) {
		syslog(LOG_ERR, "sysctlbyname(%s, buf, ...): %m", varname);
		free(buf);
		return -1;
	}

	so_begin = buf;
	so_end = (uint8_t *)buf + len;
	for (so_begin = buf, so_end = (uint8_t *)so_begin + len;
	     (uint8_t *)so_begin + sizeof(size_t) < (uint8_t *)so_end &&
	     (uint8_t *)so_begin + *(size_t *)so_begin <= (uint8_t *)so_end;
	     so_begin = (uint8_t *)so_begin + *(size_t *)so_begin) {
		switch (proto) {
		case IPPROTO_TCP:
			xtp = (struct xtcpcb *)so_begin;
			if (xtp->xt_len != sizeof *xtp) {
				syslog(LOG_WARNING, "struct xtcpcb size mismatch; %ld vs %ld",
				       (long)xtp->xt_len, sizeof *xtp);
				free(buf);
				return -1;
			}
			inp = &xtp->xt_inp;
			break;
		case IPPROTO_UDP:
			xip = (struct xinpcb *)so_begin;
			if (xip->xi_len != sizeof *xip) {
				syslog(LOG_WARNING, "struct xinpcb size mismatch : %ld vs %ld",
				       (long)xip->xi_len, sizeof *xip);
				free(buf);
				return -1;
			}
			inp = &xip->xi_inp;
			break;
		default:
			abort();
		}
		/* no support for IPv6 */
		if ((inp->inp_vflag & INP_IPV6) != 0)
			continue;
		syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu <=> %hu %08lx:%hu",
		       (u_long)inp->inp_laddr.s_addr, ntohs(inp->inp_lport),
		       (u_long)inp->inp_faddr.s_addr, ntohs(inp->inp_fport),
		       eport, (u_long)ip_addr.s_addr, iport
		);
		if (eport == (unsigned)ntohs(inp->inp_lport)) {
			if (inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_laddr.s_addr == ip_addr.s_addr) {
				found++;
				break;  /* don't care how many, just that we found at least one */
			}
		}
	}
	if(buf) {
		free(buf);
		buf = NULL;
	}
#elif defined(__FreeBSD__)
	const char *varname;
	struct xinpgen *xig, *exig;
	struct xinpcb *xip;
	struct xtcpcb *xtp;
	struct inpcb *inp;
	void *buf = NULL;
	size_t len;

	switch (proto) {
	case IPPROTO_TCP:
		varname = "net.inet.tcp.pcblist";
		break;
	case IPPROTO_UDP:
		varname = "net.inet.udp.pcblist";
		break;
	default:
		syslog(LOG_ERR, "port_in_use() unknown proto=%d", proto);
		return -1;
	}

	if (sysctlbyname(varname, NULL, &len, NULL, 0) < 0) {
		syslog(LOG_ERR, "sysctlbyname(%s, NULL, ...): %m", varname);
		return -1;
	}
	buf = malloc(len);
	if (buf == NULL) {
		syslog(LOG_ERR, "malloc(%u) failed", (unsigned)len);
		return -1;
	}
	if (sysctlbyname(varname, buf, &len, NULL, 0) < 0) {
		syslog(LOG_ERR, "sysctlbyname(%s, buf, ...): %m", varname);
		free(buf);
		return -1;
	}

	xig = (struct xinpgen *)buf;
	exig = (struct xinpgen *)(void *)((char *)buf + len - sizeof *exig);
	if (xig->xig_len != sizeof *xig) {
		syslog(LOG_WARNING, "struct xinpgen size mismatch; %ld vs %ld",
		       (long)xig->xig_len, sizeof *xig);
		free(buf);
		return -1;
	}
	if (exig->xig_len != sizeof *exig) {
		syslog(LOG_WARNING, "struct xinpgen size mismatch; %ld vs %ld",
		       (long)exig->xig_len, sizeof *exig);
		free(buf);
		return -1;
	}

	while (1) {
		xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
		if (xig >= exig)
			break;
		switch (proto) {
		case IPPROTO_TCP:
			xtp = (struct xtcpcb *)xig;
			if (xtp->xt_len != sizeof *xtp) {
				syslog(LOG_WARNING, "struct xtcpcb size mismatch; %ld vs %ld",
				       (long)xtp->xt_len, sizeof *xtp);
				free(buf);
				return -1;
			}
			inp = &xtp->xt_inp;
			break;
		case IPPROTO_UDP:
			xip = (struct xinpcb *)xig;
			if (xip->xi_len != sizeof *xip) {
				syslog(LOG_WARNING, "struct xinpcb size mismatch : %ld vs %ld",
				       (long)xip->xi_len, sizeof *xip);
				free(buf);
				return -1;
			}
			inp = &xip->xi_inp;
			break;
		default:
			abort();
		}
		/* no support for IPv6 */
		if ((inp->inp_vflag & INP_IPV6) != 0)
			continue;
		syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu <=> %hu %08lx:%hu",
		       (u_long)inp->inp_laddr.s_addr, ntohs(inp->inp_lport),
		       (u_long)inp->inp_faddr.s_addr, ntohs(inp->inp_fport),
		       eport, (u_long)ip_addr.s_addr, iport
		);
		if (eport == (unsigned)ntohs(inp->inp_lport)) {
			if (inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_laddr.s_addr == ip_addr.s_addr) {
				found++;
				break;  /* don't care how many, just that we found at least one */
			}
		}
	}
	if (buf) {
		free(buf);
		buf = NULL;
	}
/* #elif __NetBSD__ */
#else
/* TODO : NetBSD / Darwin (OS X) / Solaris code */
#error "No port_in_use() implementation available for this OS"
#endif

	/* Phase 2 : check existing mappings
	 * TODO : implement for pf/ipfw/etc. */
#if defined(USE_NETFILTER)
	if (!found) {
		char iaddr_old[16];
		unsigned short iport_old;
		int i;
		for (i = 0; chains_to_check[i]; i++) {
			if (get_nat_redirect_rule(chains_to_check[i], if_name, eport, proto,
					iaddr_old, sizeof(iaddr_old), &iport_old,
					0, 0, 0, 0, 0, 0, 0) == 0)
			{
				syslog(LOG_DEBUG, "port_in_use check port %d on nat chain %s redirected to %s port %d", eport,
						chains_to_check[i], iaddr_old, iport_old);
				if (!(strcmp(iaddr, iaddr_old)==0 && iport==iport_old)) {
					/* only "in use" if redirected to somewhere else */
					found++;
					break;  /* don't care how many, just that we found at least one */
				}
			}
		}
	}
#else /* USE_NETFILTER */
	UNUSED(iport); UNUSED(iaddr);
#endif /* USE_NETFILTER */
	return found;
}
Ejemplo n.º 21
0
/* parselanaddr()
 * parse address with mask
 * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0
 * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
 * external interface associated with the lan subnet follows.
 * ex : 192.168.1.1/24 81.21.41.11
 *
 * Can also use the interface name (ie eth0)
 *
 * return value :
 *    0 : ok
 *   -1 : error */
static int
parselanaddr(struct lan_addr_s * lan_addr, const char * str)
{
	const char * p;
	int n;
	char tmp[16];

	memset(lan_addr, 0, sizeof(struct lan_addr_s));
	p = str;
	while(*p && *p != '/' && !isspace(*p))
		p++;
	n = p - str;
	if(!isdigit(str[0]) && n < (int)sizeof(lan_addr->ifname))
	{
		/* not starting with a digit : suppose it is an interface name */
		memcpy(lan_addr->ifname, str, n);
		lan_addr->ifname[n] = '\0';
		if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str)) < 0)
			goto parselan_error;
	}
	else
	{
		if(n>15)
			goto parselan_error;
		memcpy(lan_addr->str, str, n);
		lan_addr->str[n] = '\0';
	}
	if(!inet_aton(lan_addr->str, &lan_addr->addr))
		goto parselan_error;
	if(*p == '/')
	{
		const char * q = ++p;
		while(*p && isdigit(*p))
			p++;
		if(*p=='.')
		{
			while(*p && (*p=='.' || isdigit(*p)))
				p++;
			n = p - q;
			if(n>15)
				goto parselan_error;
			memcpy(tmp, q, n);
			tmp[n] = '\0';
			if(!inet_aton(tmp, &lan_addr->mask))
				goto parselan_error;
		}
		else
		{
			int nbits = atoi(q);
			if(nbits > 32 || nbits < 0)
				goto parselan_error;
			lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0);
		}
	}
	else
	{
		/* by default, networks are /24 */
		lan_addr->mask.s_addr = htonl(0xffffff00u);
	}
#ifdef MULTIPLE_EXTERNAL_IP
	/* skip spaces */
	while(*p && isspace(*p))
		p++;
	if(*p) {
		/* parse the exteral ip address to associate with this subnet */
		n = 0;
		while(p[n] && !isspace(*p))
			n++;
		if(n<=15) {
			memcpy(lan_addr->ext_ip_str, p, n);
			lan_addr->ext_ip_str[n] = '\0';
			if(!inet_aton(lan_addr->ext_ip_str, &lan_addr->ext_ip_addr)) {
				/* error */
				fprintf(stderr, "Error parsing address : %s\n", lan_addr->ext_ip_str);
			}
		}
	}
#endif
#ifdef ENABLE_IPV6
	if(lan_addr->ifname[0] != '\0')
	{
		lan_addr->index = if_nametoindex(lan_addr->ifname);
		if(lan_addr->index == 0)
			fprintf(stderr, "Cannot get index for network interface %s",
			        lan_addr->ifname);
	}
#endif
	return 0;
parselan_error:
	fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n",
	        str);
	return -1;
}