Надлежащая длина сокета AF_UNIX при вызове связывает ()

свяжите (), нуждается в длине sockaddr структуры, которую Вы дали ей. Теперь, для сокетов Unix, sockaddr_un используется

Каковы надлежащие способы вычислить длину этого, когда Вы заполнили sun_path участник? Я видел несколько подходов:

socklen_t len = sizeof(sockaddr_un);
socklen_t len = offsetof(sockaddr_un,sun_path) + strlen(addr.sun_path);
socklen_t len = offsetof(sockaddr_un,sun_path) + strlen(addr.sun_path) + 1;
socklen_t len = sizeof(sockaddr.sun_family  ) + strlen(addr.sun_path);

И даже другие подходы. Это в порядке, чтобы просто взять sizeof (sockaddr_un) - или каков надлежащий путь?

9
задан nos 21 February 2010 в 22:30
поделиться

2 ответа

sizeof(struct sockaddr_un) в порядке.

Посмотрите на manpage unix(7). Поле sun_path - это символьный массив, который является частью struct.

3
ответ дан 3 November 2019 в 00:01
поделиться

Вы должны использовать макрос SUN_LEN . Вот из /usr/include/sys/un.h на моем Mac:

#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
/* actual length of an initialized sockaddr_un */
#define SUN_LEN(su) \
        (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif  /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */

Изменить:

Да, он не переносится и не POSIX, но мы работаем на реальных платформах, не так ли? ?

Дело в том, что вам нужно завершить путь нулями, и приведенный выше код не хуже sizeof (struct sockaddr_un) , но может сэкономить несколько байтов при копировании от пользователя к ядру, но тратит впустую несколько циклов в strlen .

Посмотрите, как Linux обрабатывает эту длину (из http://lxr.linux.no/linux+v2.6.32/net/unix/af_unix.c#L200 ):

static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp)
{
    if (len <= sizeof(short) || len > sizeof(*sunaddr))
        return -EINVAL;
    if (!sunaddr || sunaddr->sun_family != AF_UNIX)
        return -EINVAL;
    if (sunaddr->sun_path[0]) {
        /*
         * This may look like an off by one error but it is a bit more
         * subtle. 108 is the longest valid AF_UNIX path for a binding.
         * sun_path[108] doesnt as such exist.  However in kernel space
         * we are guaranteed that it is a valid memory location in our
         * kernel address buffer.
         */
        ((char *)sunaddr)[len] = 0;
        len = strlen(sunaddr->sun_path)+1+sizeof(short);
        return len;
    }

    *hashp = unix_hash_fold(csum_partial(sunaddr, len, 0));
    return len;
}

Здесь len напрямую из третьего аргумента системного вызова bind , но sunaddr уже скопирован в пространство ядра с такой длиной. У вас не может быть адреса длиннее sizeof (sockadd_un) . Ядро все равно выполняет strlen .

Так что да, выполнение sizeof (sockaddr_un) , вероятно, безопаснее во всех отношениях, но указание точной длины ядра тоже не повредит.

9
ответ дан 3 November 2019 в 00:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: