void *chg_uid_gid(void *arg) { cap_t newcaps; cap_t mycaps; int ret; test_msg("Aux thread runs as UID: %d; GID: %d\n", getuid(), getgid()); newcaps = cap_from_text("cap_setgid,cap_setuid=+eip"); if (!newcaps) { pr_perror("Failed to get capability struct\n"); exit(1); } ret = cap_set_proc(newcaps); if (ret) { pr_perror("Failed to set capabilities for the process\n"); exit(1); } mycaps = cap_get_proc(); if (!mycaps) { pr_perror("Failed to get child thread capabilities\n"); exit_group(2); } test_msg("Child capabilities: %s\n", cap_to_text(mycaps, NULL)); test_msg("Changing UID/GID in child thread to %d:%d\n", uid, gid); ret = syscall(SYS_setresgid, gid, gid, gid); if (ret >= 0) { syscall(SYS_setresuid, uid, uid, uid); } else if (ret < 0) { pr_perror("Failed to change UID/GID\n"); exit_group(2); } gid = getgid(); uid = getuid(); test_msg("Now aux thread runs as UID: %d; GID: %d\n", uid, gid); test_msg("Child thread is waiting for main thread's signal\n"); task_waiter_complete(&t, 1); pthread_mutex_lock(&mutex); while (!done) { pthread_cond_wait(&cond, &mutex); } pthread_mutex_unlock(&mutex); test_msg("Child thread returns\n"); return NULL; }
void process_igmp(struct map *group_table, uint32_t src_ip, const uint8_t *buffer, int len) { if( checksum(buffer, len) != 0) return; if(len == IGMP_HEADER_LEN){ //igmp v1, v2` const struct igmphdr *igmp = (const struct igmphdr *) buffer; uint32_t groupid = igmp->groupid; switch( igmp->type ){ case QUERY_REPORT: /*controller cannot receive query report packet*/ break; case V1_MEMBERSHIP_REPORT: /*same as V2_MEMBERSHIP_REPORT...*/ case V2_MEMBERSHIP_REPORT: enter_group(group_table, groupid, src_ip); break; case V2_LEAVE_GROUP: exit_group(group_table, groupid, src_ip); break; default: /*error*/ break; } }else if(len >= IGMP_V3_REPORT_HEADER_LEN){ //igmp v3 const struct igmpv3_report *igmpv3_pkt = (const struct igmpv3_report *) buffer; /*only deal with membership report*/ if(igmpv3_pkt->type != V3_MEMBERSHIP_REPORT) return; uint16_t ngrecord = ntohs(igmpv3_pkt->ngrecord); const uint8_t *grecord = (const uint8_t *) igmpv3_pkt->grec; int i; /*deal with each record*/ for(i = 0; i < ngrecord; i++){ uint8_t grec_type = *grecord++; uint8_t grec_auxdlen = *grecord++; //一般为0,不为0,则要跳过末尾的grec_auxdlen个字节 uint16_t grec_nsrc = ntohs(*((const uint16_t *)grecord)); grecord += sizeof(uint16_t); uint32_t grec_mcaddr = ntohl(*((const uint32_t *)grecord)); grecord += sizeof(uint32_t); switch( grec_type ){ case V3_MODE_IS_INCLUDE: //接收来自源,如果源为空则, 为退出报告,否则加入组 if( grec_nsrc == 0){ //INCLUDE{}, 表示退出报告 exit_group(group_table, grec_mcaddr, src_ip); }else{ //不为0,表示对源进行控制,现在不对源进行控制,只进行插入 enter_group(group_table, grec_mcaddr, src_ip); } break; case V3_MODE_IS_EXCLUDE: if( grec_nsrc == 0){ //EXCLUDE{}, 表示组加入报告 enter_group(group_table, grec_mcaddr, src_ip); }else{ //不为0,表示对源进行控制,现在不对源进行控制,只进行插入 enter_group(group_table, grec_mcaddr, src_ip); } break; case V3_CHANGE_TO_INCLUDE: //源地址不为空,则当做插入,否则当做退出操作 if( grec_nsrc == 0){ exit_group(group_table, grec_mcaddr, src_ip); }else{ enter_group(group_table, grec_mcaddr, src_ip); } break; case V3_CHANGE_TO_EXCLUDE: //暂时当做插入处理 enter_group(group_table, grec_mcaddr, src_ip); break; case V3_ALLOW_NEW_SOURCE: //不处理 break; case V3_BLOCK_OLD_SOURCE: //不处理 break; default: /*error*/ break; } grecord += sizeof(uint32_t) * grec_nsrc + grec_auxdlen; //step to next record } }else{ /*error, drop */ return; } return; }
int exit(void) { exit_group(); }