diff --git a/bin/stty/stty.1 b/bin/stty/stty.1 --- a/bin/stty/stty.1 +++ b/bin/stty/stty.1 @@ -32,7 +32,7 @@ .\" @(#)stty.1 8.4 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd May 24, 2022 +.Dd September 27, 2022 .Dt STTY 1 .Os .Sh NAME @@ -40,7 +40,7 @@ .Nd set the options for a terminal device interface .Sh SYNOPSIS .Nm -.Op Fl a | e | g +.Op Fl a | e | g | i .Op Fl f Ar file .Op Ar arguments .Sh DESCRIPTION @@ -85,6 +85,23 @@ .Nm to restore the current terminal state as per .St -p1003.2 . +.It Fl i +Allow +.Nm +to change terminal settings even when executing in background +process group (see description of the job control in +.Xr termios 4 ) . +.Pp +Normally, such attempt results in kernel sending the +.Va SIGTTOU +signal and stopping the process until its group is returned +to foreground. +Using this option makes +.Nm +ignore +.Va SIGTTOU . +Note that changing terminal settings for running foreground +job that is not prepared for it might cause inconsistencies. .El .Pp The following arguments are available to set the terminal @@ -607,9 +624,10 @@ .St -p1003.2 compatible. The flags -.Fl e -and +.Fl e , .Fl f +and +.Fl i are extensions to the standard. .Sh HISTORY diff --git a/bin/stty/stty.c b/bin/stty/stty.c --- a/bin/stty/stty.c +++ b/bin/stty/stty.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,7 @@ main(int argc, char *argv[]) { struct info i; + struct sigaction sa; enum FMT fmt; int ch; const char *file, *errstr = NULL; @@ -69,8 +71,8 @@ opterr = 0; while (optind < argc && - strspn(argv[optind], "-aefg") == strlen(argv[optind]) && - (ch = getopt(argc, argv, "aef:g")) != -1) + strspn(argv[optind], "-aefgi") == strlen(argv[optind]) && + (ch = getopt(argc, argv, "aef:gi")) != -1) switch(ch) { case 'a': /* undocumented: POSIX compatibility */ fmt = POSIX; @@ -86,6 +88,12 @@ case 'g': fmt = GFLAG; break; + case 'i': + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + if (sigaction(SIGTTOU, &sa, NULL) == -1) + err(1, "sigaction"); + break; case '?': default: goto args; @@ -161,6 +169,6 @@ { (void)fprintf(stderr, - "usage: stty [-a | -e | -g] [-f file] [arguments]\n"); + "usage: stty [-a | -e | -g] [-i] [-f file] [arguments]\n"); exit (1); } diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -817,51 +817,35 @@ } /* State of the bootstrapped DMAP page tables */ -struct pmap_bootstrap_state { +struct dmap_bootstrap_state { vm_offset_t va; vm_paddr_t pa; pt_entry_t *l1; pt_entry_t *l2; pt_entry_t *l3; - pt_entry_t table_attrs; u_int l0_slot; u_int l1_slot; u_int l2_slot; vm_offset_t freemempos; - bool dmap_valid; -}; - -/* The bootstrap state */ -static struct pmap_bootstrap_state bs_state = { - .l1 = NULL, - .l2 = NULL, - .l3 = NULL, - .table_attrs = TATTR_PXN_TABLE, - .l0_slot = L0_ENTRIES, - .l1_slot = Ln_ENTRIES, - .l2_slot = Ln_ENTRIES, - .dmap_valid = false, }; static void -pmap_bootstrap_l0_table(struct pmap_bootstrap_state *state) +pmap_bootstrap_dmap_l0_table(struct dmap_bootstrap_state *state) { vm_paddr_t l1_pa; - pd_entry_t l0e; u_int l0_slot; /* Link the level 0 table to a level 1 table */ l0_slot = pmap_l0_index(state->va); if (l0_slot != state->l0_slot) { - /* - * Make sure we move from a low address to high address - * before the DMAP region is ready. This ensures we never - * modify an existing mapping until we can map from a - * physical address to a virtual address. - */ MPASS(state->l0_slot < l0_slot || - state->l0_slot == L0_ENTRIES || - state->dmap_valid); + state->l0_slot == L0_ENTRIES); + + /* Create a new L0 table entry */ + state->l0_slot = l0_slot; + state->l1 = (pt_entry_t *)state->freemempos; + memset(state->l1, 0, PAGE_SIZE); + state->freemempos += PAGE_SIZE; /* Reset lower levels */ state->l2 = NULL; @@ -869,23 +853,6 @@ state->l1_slot = Ln_ENTRIES; state->l2_slot = Ln_ENTRIES; - /* Check the existing L0 entry */ - state->l0_slot = l0_slot; - if (state->dmap_valid) { - l0e = pagetable_l0_ttbr1[l0_slot]; - if ((l0e & ATTR_DESCR_VALID) != 0) { - MPASS((l0e & ATTR_DESCR_MASK) == L0_TABLE); - l1_pa = l0e & ~ATTR_MASK; - state->l1 = (pt_entry_t *)PHYS_TO_DMAP(l1_pa); - return; - } - } - - /* Create a new L0 table entry */ - state->l1 = (pt_entry_t *)state->freemempos; - memset(state->l1, 0, PAGE_SIZE); - state->freemempos += PAGE_SIZE; - l1_pa = pmap_early_vtophys((vm_offset_t)state->l1); MPASS((l1_pa & Ln_TABLE_MASK) == 0); MPASS(pagetable_l0_ttbr1[l0_slot] == 0); @@ -896,84 +863,56 @@ } static void -pmap_bootstrap_l1_table(struct pmap_bootstrap_state *state) +pmap_bootstrap_dmap_l1_table(struct dmap_bootstrap_state *state) { vm_paddr_t l2_pa; - pd_entry_t l1e; u_int l1_slot; /* Make sure there is a valid L0 -> L1 table */ - pmap_bootstrap_l0_table(state); + pmap_bootstrap_dmap_l0_table(state); /* Link the level 1 table to a level 2 table */ l1_slot = pmap_l1_index(state->va); if (l1_slot != state->l1_slot) { - /* See pmap_bootstrap_l0_table for a description */ MPASS(state->l1_slot < l1_slot || - state->l1_slot == Ln_ENTRIES || - state->dmap_valid); - - /* Reset lower levels */ - state->l3 = NULL; - state->l2_slot = Ln_ENTRIES; - - /* Check the existing L1 entry */ - state->l1_slot = l1_slot; - if (state->dmap_valid) { - l1e = state->l1[l1_slot]; - if ((l1e & ATTR_DESCR_VALID) != 0) { - MPASS((l1e & ATTR_DESCR_MASK) == L1_TABLE); - l2_pa = l1e & ~ATTR_MASK; - state->l2 = (pt_entry_t *)PHYS_TO_DMAP(l2_pa); - return; - } - } + state->l1_slot == Ln_ENTRIES); /* Create a new L1 table entry */ + state->l1_slot = l1_slot; state->l2 = (pt_entry_t *)state->freemempos; memset(state->l2, 0, PAGE_SIZE); state->freemempos += PAGE_SIZE; + /* Reset lower levels */ + state->l3 = NULL; + state->l2_slot = Ln_ENTRIES; + l2_pa = pmap_early_vtophys((vm_offset_t)state->l2); MPASS((l2_pa & Ln_TABLE_MASK) == 0); MPASS(state->l1[l1_slot] == 0); - pmap_store(&state->l1[l1_slot], l2_pa | state->table_attrs | + pmap_store(&state->l1[l1_slot], l2_pa | TATTR_PXN_TABLE | L1_TABLE); } KASSERT(state->l2 != NULL, ("%s: NULL l2", __func__)); } static void -pmap_bootstrap_l2_table(struct pmap_bootstrap_state *state) +pmap_bootstrap_dmap_l2_table(struct dmap_bootstrap_state *state) { vm_paddr_t l3_pa; - pd_entry_t l2e; u_int l2_slot; /* Make sure there is a valid L1 -> L2 table */ - pmap_bootstrap_l1_table(state); + pmap_bootstrap_dmap_l1_table(state); /* Link the level 2 table to a level 3 table */ l2_slot = pmap_l2_index(state->va); if (l2_slot != state->l2_slot) { - /* See pmap_bootstrap_l0_table for a description */ MPASS(state->l2_slot < l2_slot || - state->l2_slot == Ln_ENTRIES || - state->dmap_valid); - - /* Check the existing L2 entry */ - state->l2_slot = l2_slot; - if (state->dmap_valid) { - l2e = state->l2[l2_slot]; - if ((l2e & ATTR_DESCR_VALID) != 0) { - MPASS((l2e & ATTR_DESCR_MASK) == L2_TABLE); - l3_pa = l2e & ~ATTR_MASK; - state->l3 = (pt_entry_t *)PHYS_TO_DMAP(l3_pa); - return; - } - } + state->l2_slot == Ln_ENTRIES); /* Create a new L2 table entry */ + state->l2_slot = l2_slot; state->l3 = (pt_entry_t *)state->freemempos; memset(state->l3, 0, PAGE_SIZE); state->freemempos += PAGE_SIZE; @@ -981,14 +920,14 @@ l3_pa = pmap_early_vtophys((vm_offset_t)state->l3); MPASS((l3_pa & Ln_TABLE_MASK) == 0); MPASS(state->l2[l2_slot] == 0); - pmap_store(&state->l2[l2_slot], l3_pa | state->table_attrs | + pmap_store(&state->l2[l2_slot], l3_pa | TATTR_PXN_TABLE | L2_TABLE); } KASSERT(state->l3 != NULL, ("%s: NULL l3", __func__)); } static void -pmap_bootstrap_l2_block(struct pmap_bootstrap_state *state, int i) +pmap_bootstrap_dmap_l2_block(struct dmap_bootstrap_state *state, int i) { u_int l2_slot; bool first; @@ -997,7 +936,7 @@ return; /* Make sure there is a valid L1 table */ - pmap_bootstrap_l1_table(state); + pmap_bootstrap_dmap_l1_table(state); MPASS((state->va & L2_OFFSET) == 0); for (first = true; @@ -1023,7 +962,7 @@ } static void -pmap_bootstrap_l3_page(struct pmap_bootstrap_state *state, int i) +pmap_bootstrap_dmap_l3_page(struct dmap_bootstrap_state *state, int i) { u_int l3_slot; bool first; @@ -1032,7 +971,7 @@ return; /* Make sure there is a valid L2 table */ - pmap_bootstrap_l2_table(state); + pmap_bootstrap_dmap_l2_table(state); MPASS((state->va & L3_OFFSET) == 0); for (first = true; @@ -1061,97 +1000,130 @@ pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t min_pa, vm_offset_t freemempos) { + struct dmap_bootstrap_state state; int i; dmap_phys_base = min_pa & ~L1_OFFSET; dmap_phys_max = 0; dmap_max_addr = 0; - bs_state.freemempos = freemempos; + state.l1 = state.l2 = state.l3 = NULL; + state.l0_slot = L0_ENTRIES; + state.l1_slot = Ln_ENTRIES; + state.l2_slot = Ln_ENTRIES; + state.freemempos = freemempos; for (i = 0; i < (physmap_idx * 2); i += 2) { - bs_state.pa = physmap[i] & ~L3_OFFSET; - bs_state.va = bs_state.pa - dmap_phys_base + DMAP_MIN_ADDRESS; + state.pa = physmap[i] & ~L3_OFFSET; + state.va = state.pa - dmap_phys_base + DMAP_MIN_ADDRESS; /* Create L3 mappings at the start of the region */ - if ((bs_state.pa & L2_OFFSET) != 0) - pmap_bootstrap_l3_page(&bs_state, i); - MPASS(bs_state.pa <= physmap[i + 1]); + if ((state.pa & L2_OFFSET) != 0) + pmap_bootstrap_dmap_l3_page(&state, i); + MPASS(state.pa <= physmap[i + 1]); if (L1_BLOCKS_SUPPORTED) { /* Create L2 mappings at the start of the region */ - if ((bs_state.pa & L1_OFFSET) != 0) - pmap_bootstrap_l2_block(&bs_state, i); - MPASS(bs_state.pa <= physmap[i + 1]); + if ((state.pa & L1_OFFSET) != 0) + pmap_bootstrap_dmap_l2_block(&state, i); + MPASS(state.pa <= physmap[i + 1]); /* Create the main L1 block mappings */ - for (; bs_state.va < DMAP_MAX_ADDRESS && - (physmap[i + 1] - bs_state.pa) >= L1_SIZE; - bs_state.va += L1_SIZE, bs_state.pa += L1_SIZE) { + for (; state.va < DMAP_MAX_ADDRESS && + (physmap[i + 1] - state.pa) >= L1_SIZE; + state.va += L1_SIZE, state.pa += L1_SIZE) { /* Make sure there is a valid L1 table */ - pmap_bootstrap_l0_table(&bs_state); - MPASS((bs_state.pa & L1_OFFSET) == 0); - pmap_store( - &bs_state.l1[pmap_l1_index(bs_state.va)], - bs_state.pa | ATTR_DEFAULT | ATTR_S1_XN | + pmap_bootstrap_dmap_l0_table(&state); + MPASS((state.pa & L1_OFFSET) == 0); + pmap_store(&state.l1[pmap_l1_index(state.va)], + state.pa | ATTR_DEFAULT | ATTR_S1_XN | ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | L1_BLOCK); } - MPASS(bs_state.pa <= physmap[i + 1]); + MPASS(state.pa <= physmap[i + 1]); /* Create L2 mappings at the end of the region */ - pmap_bootstrap_l2_block(&bs_state, i); + pmap_bootstrap_dmap_l2_block(&state, i); } else { - while (bs_state.va < DMAP_MAX_ADDRESS && - (physmap[i + 1] - bs_state.pa) >= L2_SIZE) { - pmap_bootstrap_l2_block(&bs_state, i); + while (state.va < DMAP_MAX_ADDRESS && + (physmap[i + 1] - state.pa) >= L2_SIZE) { + pmap_bootstrap_dmap_l2_block(&state, i); } } - MPASS(bs_state.pa <= physmap[i + 1]); + MPASS(state.pa <= physmap[i + 1]); /* Create L3 mappings at the end of the region */ - pmap_bootstrap_l3_page(&bs_state, i); - MPASS(bs_state.pa == physmap[i + 1]); + pmap_bootstrap_dmap_l3_page(&state, i); + MPASS(state.pa == physmap[i + 1]); - if (bs_state.pa > dmap_phys_max) { - dmap_phys_max = bs_state.pa; - dmap_max_addr = bs_state.va; + if (state.pa > dmap_phys_max) { + dmap_phys_max = state.pa; + dmap_max_addr = state.va; } } cpu_tlb_flushID(); - return (bs_state.freemempos); + return (state.freemempos); } static vm_offset_t pmap_bootstrap_l2(vm_offset_t l1pt, vm_offset_t va, vm_offset_t l2_start) { + vm_offset_t l2pt; + vm_paddr_t pa; + pd_entry_t *l1; + u_int l1_slot; + KASSERT((va & L1_OFFSET) == 0, ("Invalid virtual address")); - /* Leave bs_state.pa as it's only needed to bootstrap blocks and pages*/ - bs_state.va = va; - bs_state.freemempos = l2_start; + l1 = (pd_entry_t *)l1pt; + l1_slot = pmap_l1_index(va); + l2pt = l2_start; - for (; bs_state.va < VM_MAX_KERNEL_ADDRESS; bs_state.va += L1_SIZE) - pmap_bootstrap_l1_table(&bs_state); + for (; va < VM_MAX_KERNEL_ADDRESS; l1_slot++, va += L1_SIZE) { + KASSERT(l1_slot < Ln_ENTRIES, ("Invalid L1 index")); + + pa = pmap_early_vtophys(l2pt); + pmap_store(&l1[l1_slot], + (pa & ~Ln_TABLE_MASK) | L1_TABLE); + l2pt += PAGE_SIZE; + } - return (bs_state.freemempos); + /* Clean the L2 page table */ + memset((void *)l2_start, 0, l2pt - l2_start); + + return l2pt; } static vm_offset_t pmap_bootstrap_l3(vm_offset_t l1pt, vm_offset_t va, vm_offset_t l3_start) { + vm_offset_t l3pt; + vm_paddr_t pa; + pd_entry_t *l2; + u_int l2_slot; + KASSERT((va & L2_OFFSET) == 0, ("Invalid virtual address")); - /* Leave bs_state.pa as it's only needed to bootstrap blocks and pages*/ - bs_state.va = va; - bs_state.freemempos = l3_start; + l2 = pmap_l2(kernel_pmap, va); + l2 = (pd_entry_t *)rounddown2((uintptr_t)l2, PAGE_SIZE); + l2_slot = pmap_l2_index(va); + l3pt = l3_start; + + for (; va < VM_MAX_KERNEL_ADDRESS; l2_slot++, va += L2_SIZE) { + KASSERT(l2_slot < Ln_ENTRIES, ("Invalid L2 index")); + + pa = pmap_early_vtophys(l3pt); + pmap_store(&l2[l2_slot], + (pa & ~Ln_TABLE_MASK) | ATTR_S1_UXN | L2_TABLE); + l3pt += PAGE_SIZE; + } - for (; bs_state.va < VM_MAX_KERNEL_ADDRESS; bs_state.va += L2_SIZE) - pmap_bootstrap_l2_table(&bs_state); + /* Clean the L2 page table */ + memset((void *)l3_start, 0, l3pt - l3_start); - return (bs_state.freemempos); + return l3pt; } /* @@ -1209,12 +1181,6 @@ /* Create a direct map region early so we can use it for pa -> va */ freemempos = pmap_bootstrap_dmap(l1pt, min_pa, freemempos); - bs_state.dmap_valid = true; - /* - * We only use PXN when we know nothing will be executed from it, e.g. - * the DMAP region. - */ - bs_state.table_attrs &= ~TATTR_PXN_TABLE; start_pa = pa = KERNBASE - kern_delta; diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c --- a/sys/net/if_epair.c +++ b/sys/net/if_epair.c @@ -184,13 +184,39 @@ if_rele(sc->ifp); } -static struct epair_queue * -epair_select_queue(struct epair_softc *sc, const struct mbuf *m) +static int +epair_menq(struct mbuf *m, struct epair_softc *osc) { + struct ifnet *ifp, *oifp; + int len, ret; + int ridx; + short mflags; + struct epair_queue *q = NULL; uint32_t bucket; #ifdef RSS struct ether_header *eh; +#endif + + /* + * I know this looks weird. We pass the "other sc" as we need that one + * and can get both ifps from it as well. + */ + oifp = osc->ifp; + ifp = osc->oifp; + + M_ASSERTPKTHDR(m); + epair_clear_mbuf(m); + if_setrcvif(m, oifp); + M_SETFIB(m, oifp->if_fib); + + /* Save values as once the mbuf is queued, it's not ours anymore. */ + len = m->m_pkthdr.len; + mflags = m->m_flags; + + MPASS(m->m_nextpkt == NULL); + MPASS((m->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0); +#ifdef RSS ret = rss_m2bucket(m, &bucket); if (ret) { /* Actually hash the packet. */ @@ -212,47 +238,11 @@ break; } } - bucket %= sc->num_queues; + bucket %= osc->num_queues; #else bucket = 0; #endif - return (&sc->queues[bucket]); -} - -static void -epair_prepare_mbuf(struct mbuf *m, struct ifnet *src_ifp) -{ - M_ASSERTPKTHDR(m); - epair_clear_mbuf(m); - if_setrcvif(m, src_ifp); - M_SETFIB(m, src_ifp->if_fib); - - MPASS(m->m_nextpkt == NULL); - MPASS((m->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0); -} - -static void -epair_menq(struct mbuf *m, struct epair_softc *osc) -{ - struct ifnet *ifp, *oifp; - int len, ret; - int ridx; - short mflags; - - /* - * I know this looks weird. We pass the "other sc" as we need that one - * and can get both ifps from it as well. - */ - oifp = osc->ifp; - ifp = osc->oifp; - - epair_prepare_mbuf(m, oifp); - - /* Save values as once the mbuf is queued, it's not ours anymore. */ - len = m->m_pkthdr.len; - mflags = m->m_flags; - - struct epair_queue *q = epair_select_queue(osc, m); + q = &osc->queues[bucket]; atomic_set_long(&q->state, (1 << BIT_MBUF_QUEUED)); ridx = atomic_load_int(&q->ridx); @@ -261,7 +251,7 @@ /* Ring is full. */ if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1); m_freem(m); - return; + return (0); } if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); @@ -277,7 +267,9 @@ if_inc_counter(oifp, IFCOUNTER_IPACKETS, 1); if (!atomic_testandset_long(&q->state, BIT_QUEUE_TASK)) - taskqueue_enqueue(epair_tasks.tq[q->id], &q->tx_task); + taskqueue_enqueue(epair_tasks.tq[bucket], &q->tx_task); + + return (0); } static void @@ -312,7 +304,7 @@ continue; } - epair_menq(m, sc); + (void) epair_menq(m, sc); } } @@ -321,6 +313,7 @@ { struct epair_softc *sc; struct ifnet *oifp; + int error; #ifdef ALTQ int len; short mflags; @@ -365,7 +358,6 @@ #ifdef ALTQ len = m->m_pkthdr.len; mflags = m->m_flags; - int error = 0; /* Support ALTQ via the classic if_start() path. */ IF_LOCK(&ifp->if_snd); @@ -385,8 +377,8 @@ IF_UNLOCK(&ifp->if_snd); #endif - epair_menq(m, oifp->if_softc); - return (0); + error = epair_menq(m, oifp->if_softc); + return (error); } static void @@ -615,23 +607,15 @@ free(sc, M_EPAIR); } -static void -epair_set_state(struct ifnet *ifp, bool running) -{ - if (running) { - ifp->if_drv_flags |= IFF_DRV_RUNNING; - if_link_state_change(ifp, LINK_STATE_UP); - } else { - if_link_state_change(ifp, LINK_STATE_DOWN); - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - } -} - static int -epair_handle_unit(struct if_clone *ifc, char *name, size_t len, int *punit) +epair_clone_create(struct if_clone *ifc, char *name, size_t len, + struct ifc_data *ifd, struct ifnet **ifpp) { - int error = 0, unit, wildcard; + struct epair_softc *sca, *scb; + struct ifnet *ifp; char *dp; + int error, unit, wildcard; + uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ /* Try to see if a special unit was requested. */ error = ifc_name2unit(name, &unit); @@ -649,55 +633,29 @@ */ for (dp = name; *dp != '\0'; dp++); if (wildcard) { - int slen = snprintf(dp, len - (dp - name), "%d", unit); - if (slen > len - (dp - name) - 1) { + error = snprintf(dp, len - (dp - name), "%d", unit); + if (error > len - (dp - name) - 1) { /* ifName too long. */ - error = ENOSPC; - goto done; + ifc_free_unit(ifc, unit); + return (ENOSPC); } - dp += slen; + dp += error; } if (len - (dp - name) - 1 < 1) { /* No space left for our [ab] suffix. */ - error = ENOSPC; - goto done; + ifc_free_unit(ifc, unit); + return (ENOSPC); } *dp = 'b'; /* Must not change dp so we can replace 'a' by 'b' later. */ *(dp+1) = '\0'; /* Check if 'a' and 'b' interfaces already exist. */ - if (ifunit(name) != NULL) { - error = EEXIST; - goto done; - } - + if (ifunit(name) != NULL) + return (EEXIST); *dp = 'a'; - if (ifunit(name) != NULL) { - error = EEXIST; - goto done; - } - *punit = unit; -done: - if (error != 0) - ifc_free_unit(ifc, unit); - - return (error); -} - -static int -epair_clone_create(struct if_clone *ifc, char *name, size_t len, - struct ifc_data *ifd, struct ifnet **ifpp) -{ - struct epair_softc *sca, *scb; - struct ifnet *ifp; - char *dp; - int error, unit; - uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ - - error = epair_handle_unit(ifc, name, len, &unit); - if (error != 0) - return (error); + if (ifunit(name) != NULL) + return (EEXIST); /* Allocate memory for both [ab] interfaces */ sca = epair_alloc_sc(ifc); @@ -723,7 +681,6 @@ ether_ifattach(ifp, eaddr); /* Swap the name and finish initialization of interface b. */ - dp = name + strlen(name) - 1; *dp = 'b'; epair_setup_ifp(scb, name, unit); @@ -743,8 +700,10 @@ strlcpy(name, sca->ifp->if_xname, len); /* Tell the world, that we are ready to rock. */ - epair_set_state(sca->ifp, true); - epair_set_state(scb->ifp, true); + sca->ifp->if_drv_flags |= IFF_DRV_RUNNING; + if_link_state_change(sca->ifp, LINK_STATE_UP); + scb->ifp->if_drv_flags |= IFF_DRV_RUNNING; + if_link_state_change(scb->ifp, LINK_STATE_UP); *ifpp = sca->ifp; @@ -791,8 +750,10 @@ scb = oifp->if_softc; /* Frist get the interfaces down and detached. */ - epair_set_state(ifp, false); - epair_set_state(oifp, false); + if_link_state_change(ifp, LINK_STATE_DOWN); + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + if_link_state_change(oifp, LINK_STATE_DOWN); + oifp->if_drv_flags &= ~IFF_DRV_RUNNING; ether_ifdetach(ifp); ether_ifdetach(oifp); diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -252,15 +252,15 @@ struct in6_ifaddr *ia = NULL; struct in6_aliasreq *ifra = (struct in6_aliasreq *)data; struct sockaddr_in6 *sa6; + int carp_attached = 0; int error; + u_long ocmd = cmd; /* * Compat to make pre-10.x ifconfig(8) operable. */ - if (cmd == OSIOCAIFADDR_IN6) { + if (cmd == OSIOCAIFADDR_IN6) cmd = SIOCAIFADDR_IN6; - ifra->ifra_vhid = 0; - } switch (cmd) { case SIOCGETSGCNT_IN6: @@ -560,9 +560,142 @@ break; case SIOCAIFADDR_IN6: - error = in6_addifaddr(ifp, ifra, ia); - ia = NULL; + { + struct nd_prefixctl pr0; + struct nd_prefix *pr; + + /* + * first, make or update the interface address structure, + * and link it to the list. + */ + if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0) + goto out; + if (ia != NULL) { + if (ia->ia_ifa.ifa_carp) + (*carp_detach_p)(&ia->ia_ifa, true); + ifa_free(&ia->ia_ifa); + } + if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr)) + == NULL) { + /* + * this can happen when the user specify the 0 valid + * lifetime. + */ + break; + } + + if (cmd == ocmd && ifra->ifra_vhid > 0) { + if (carp_attach_p != NULL) + error = (*carp_attach_p)(&ia->ia_ifa, + ifra->ifra_vhid); + else + error = EPROTONOSUPPORT; + if (error) + goto out; + else + carp_attached = 1; + } + + /* + * then, make the prefix on-link on the interface. + * XXX: we'd rather create the prefix before the address, but + * we need at least one address to install the corresponding + * interface route, so we configure the address first. + */ + + /* + * convert mask to prefix length (prefixmask has already + * been validated in in6_update_ifa(). + */ + bzero(&pr0, sizeof(pr0)); + pr0.ndpr_ifp = ifp; + pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr, + NULL); + if (pr0.ndpr_plen == 128) { + /* we don't need to install a host route. */ + goto aifaddr_out; + } + pr0.ndpr_prefix = ifra->ifra_addr; + /* apply the mask for safety. */ + IN6_MASK_ADDR(&pr0.ndpr_prefix.sin6_addr, + &ifra->ifra_prefixmask.sin6_addr); + + /* + * XXX: since we don't have an API to set prefix (not address) + * lifetimes, we just use the same lifetimes as addresses. + * The (temporarily) installed lifetimes can be overridden by + * later advertised RAs (when accept_rtadv is non 0), which is + * an intended behavior. + */ + pr0.ndpr_raf_onlink = 1; /* should be configurable? */ + pr0.ndpr_raf_auto = + ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0); + pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime; + pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime; + + /* add the prefix if not yet. */ + if ((pr = nd6_prefix_lookup(&pr0)) == NULL) { + /* + * nd6_prelist_add will install the corresponding + * interface route. + */ + if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0) { + if (carp_attached) + (*carp_detach_p)(&ia->ia_ifa, false); + goto out; + } + } + + /* relate the address to the prefix */ + if (ia->ia6_ndpr == NULL) { + ia->ia6_ndpr = pr; + pr->ndpr_addrcnt++; + + /* + * If this is the first autoconf address from the + * prefix, create a temporary address as well + * (when required). + */ + if ((ia->ia6_flags & IN6_IFF_AUTOCONF) && + V_ip6_use_tempaddr && pr->ndpr_addrcnt == 1) { + int e; + if ((e = in6_tmpifadd(ia, 1, 0)) != 0) { + log(LOG_NOTICE, "in6_control: failed " + "to create a temporary address, " + "errno=%d\n", e); + } + } + } + nd6_prefix_rele(pr); + + /* + * this might affect the status of autoconfigured addresses, + * that is, this address might make other addresses detached. + */ + pfxlist_onlink_check(); + +aifaddr_out: + /* + * Try to clear the flag when a new IPv6 address is added + * onto an IFDISABLED interface and it succeeds. + */ + if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) { + struct in6_ndireq nd; + + memset(&nd, 0, sizeof(nd)); + nd.ndi.flags = ND_IFINFO(ifp)->flags; + nd.ndi.flags &= ~ND6_IFF_IFDISABLED; + if (nd6_ioctl(SIOCSIFINFO_FLAGS, (caddr_t)&nd, ifp) < 0) + log(LOG_NOTICE, "SIOCAIFADDR_IN6: " + "SIOCSIFINFO_FLAGS for -ifdisabled " + "failed."); + /* + * Ignore failure of clearing the flag intentionally. + * The failure means address duplication was detected. + */ + } break; + } case SIOCDIFADDR_IN6: in6_purgeifaddr(ia); @@ -1191,151 +1324,6 @@ return (false); } -int -in6_addifaddr(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *ia) -{ - struct nd_prefixctl pr0; - struct nd_prefix *pr; - int carp_attached = 0; - int error; - - /* - * first, make or update the interface address structure, - * and link it to the list. - */ - if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0) - goto out; - if (ia != NULL) { - if (ia->ia_ifa.ifa_carp) - (*carp_detach_p)(&ia->ia_ifa, true); - ifa_free(&ia->ia_ifa); - } - if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr)) == NULL) { - /* - * this can happen when the user specify the 0 valid - * lifetime. - */ - return (0); - } - - if (ifra->ifra_vhid > 0) { - if (carp_attach_p != NULL) - error = (*carp_attach_p)(&ia->ia_ifa, - ifra->ifra_vhid); - else - error = EPROTONOSUPPORT; - if (error) - goto out; - else - carp_attached = 1; - } - - /* - * then, make the prefix on-link on the interface. - * XXX: we'd rather create the prefix before the address, but - * we need at least one address to install the corresponding - * interface route, so we configure the address first. - */ - - /* - * convert mask to prefix length (prefixmask has already - * been validated in in6_update_ifa(). - */ - bzero(&pr0, sizeof(pr0)); - pr0.ndpr_ifp = ifp; - pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr, - NULL); - if (pr0.ndpr_plen == 128) { - /* we don't need to install a host route. */ - goto aifaddr_out; - } - pr0.ndpr_prefix = ifra->ifra_addr; - /* apply the mask for safety. */ - IN6_MASK_ADDR(&pr0.ndpr_prefix.sin6_addr, - &ifra->ifra_prefixmask.sin6_addr); - - /* - * XXX: since we don't have an API to set prefix (not address) - * lifetimes, we just use the same lifetimes as addresses. - * The (temporarily) installed lifetimes can be overridden by - * later advertised RAs (when accept_rtadv is non 0), which is - * an intended behavior. - */ - pr0.ndpr_raf_onlink = 1; /* should be configurable? */ - pr0.ndpr_raf_auto = - ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0); - pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime; - pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime; - - /* add the prefix if not yet. */ - if ((pr = nd6_prefix_lookup(&pr0)) == NULL) { - /* - * nd6_prelist_add will install the corresponding - * interface route. - */ - if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0) { - if (carp_attached) - (*carp_detach_p)(&ia->ia_ifa, false); - goto out; - } - } - - /* relate the address to the prefix */ - if (ia->ia6_ndpr == NULL) { - ia->ia6_ndpr = pr; - pr->ndpr_addrcnt++; - - /* - * If this is the first autoconf address from the - * prefix, create a temporary address as well - * (when required). - */ - if ((ia->ia6_flags & IN6_IFF_AUTOCONF) && - V_ip6_use_tempaddr && pr->ndpr_addrcnt == 1) { - int e; - if ((e = in6_tmpifadd(ia, 1, 0)) != 0) { - log(LOG_NOTICE, "in6_control: failed " - "to create a temporary address, " - "errno=%d\n", e); - } - } - } - nd6_prefix_rele(pr); - - /* - * this might affect the status of autoconfigured addresses, - * that is, this address might make other addresses detached. - */ - pfxlist_onlink_check(); - -aifaddr_out: - /* - * Try to clear the flag when a new IPv6 address is added - * onto an IFDISABLED interface and it succeeds. - */ - if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) { - struct in6_ndireq nd; - - memset(&nd, 0, sizeof(nd)); - nd.ndi.flags = ND_IFINFO(ifp)->flags; - nd.ndi.flags &= ~ND6_IFF_IFDISABLED; - if (nd6_ioctl(SIOCSIFINFO_FLAGS, (caddr_t)&nd, ifp) < 0) - log(LOG_NOTICE, "SIOCAIFADDR_IN6: " - "SIOCSIFINFO_FLAGS for -ifdisabled " - "failed."); - /* - * Ignore failure of clearing the flag intentionally. - * The failure means address duplication was detected. - */ - } - error = 0; - -out: - if (ia != NULL) - ifa_free(&ia->ia_ifa); - return (error); -} - void in6_purgeaddr(struct ifaddr *ifa) { diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h --- a/sys/netinet6/in6_var.h +++ b/sys/netinet6/in6_var.h @@ -889,7 +889,6 @@ struct in6_ifaddr *, int); void in6_prepare_ifra(struct in6_aliasreq *, const struct in6_addr *, const struct in6_addr *); -int in6_addifaddr(struct ifnet *, struct in6_aliasreq *, struct in6_ifaddr *); void in6_purgeaddr(struct ifaddr *); void in6_purgeifaddr(struct in6_ifaddr *); int in6if_do_dad(struct ifnet *); diff --git a/sys/netpfil/pf/pf_nv.c b/sys/netpfil/pf/pf_nv.c --- a/sys/netpfil/pf/pf_nv.c +++ b/sys/netpfil/pf/pf_nv.c @@ -1067,7 +1067,6 @@ return (NULL); } nvlist_add_nvlist(nvl, "src", addr); - nvlist_destroy(addr); addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->dst); if (addr == NULL) { @@ -1075,7 +1074,6 @@ return (NULL); } nvlist_add_nvlist(nvl, "dst", addr); - nvlist_destroy(addr); addr = pf_rule_addr_to_nvrule_addr(&krule->ipsrc); if (addr == NULL) {