Network configuration on Linux — exercises with the workstation’s ID card, ifconfig commands translated and a generated ifcfg (and the /32 that left the card all alone)
In the networks practical exam we had to configure the workstation by copying the commands from the notes. I typed ip addr add 10.110.7.4 dev enp2s0, brought the card up, pinged the gateway… Network is unreachable. I checked the IP ten times: it was right. What was missing was three characters: /24. The lesson: in networking, what you don’t type counts too; without a mask, the card thinks it’s alone in the world.
These exercises close the topic after the theory and the practice. They’re done in the same isolated lab (workstation, gateway 10.110.7.1 and router 10.110.1.1), as root except where stated.
Table of Contents
How to use this article
- Read the task and the expected output.
- Solve it on a practice or virtual machine (never on your laptop) without looking at the solution. If you get stuck, open the hint.
- Before the solutions, do the three “What’s wrong here?” snippets: predict the error.
- Compare with my commands. What counts is that the output matches and that you can explain every line.
Level 1: the workstation’s ID card
The workstation is already configured. With four commands that only look, get its MAC, its IP with prefix, its default gateway and the first DNS server.
Expected output (the MAC and the number after @if will differ on your machine):
# ip -br link show enp2s0 enp2s0@if21 UP 08:00:27:a1:07:04 <BROADCAST,MULTICAST,UP,LOWER_UP> # ip -br addr show enp2s0 enp2s0@if21 UP 10.110.7.4/24 # ip route show default default via 10.110.7.1 dev enp2s0 # head -1 /etc/resolv.conf nameserver 193.145.147.22
-br also works with link, and both ip addr and ip link accept show <card>. For the DNS, the first line of a file in /etc.
Level 2: from ifconfig to ip
Some old notes have these commands to configure the workstation with the IP 10.110.7.5:
ifconfig enp2s0 up ifconfig enp2s0 10.110.7.5 netmask 255.255.255.0 broadcast 10.110.7.255 route add default gw 10.110.7.1
Translate them to ip (broadcast address included), apply them to the freshly booted workstation and check the result with ip addr show enp2s0, with the old route -n and with a 2-packet ping to the router.
Expected output:
# ip link set enp2s0 up
# ip addr add 10.110.7.5/24 brd + dev enp2s0
# ip route add default via 10.110.7.1
# ip addr show enp2s0
26: enp2s0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 08:00:27:a1:07:04 brd ff:ff:ff:ff:ff:ff link-netns gateway
inet 10.110.7.5/24 brd 10.110.7.255 scope global enp2s0
valid_lft forever preferred_lft forever
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.110.7.1 0.0.0.0 UG 0 0 0 enp2s0
10.110.7.0 0.0.0.0 255.255.255.0 U 0 0 0 enp2s0
# ping -c 2 10.110.1.1
PING 10.110.1.1 (10.110.1.1) 56(84) bytes of data.
64 bytes from 10.110.1.1: icmp_seq=1 ttl=63 time=0.233 ms
64 bytes from 10.110.1.1: icmp_seq=2 ttl=63 time=0.068 ms
--- 10.110.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1004ms
rtt min/avg/max/mdev = 0.068/0.150/0.233/0.082 ms
/24 replaces netmask 255.255.255.0, and brd + asks ip to work out the broadcast for you.
Level 3: generate the ifcfg of what’s there
You’ve configured a workstation by hand with ip and it works. Before a reboot wipes it all, write a script ifcfg-from-live.sh that, given the card’s name, prints the ifcfg that would reproduce the current configuration (DEVICE, BOOTPROTO=none, ONBOOT=yes, IPADDR, NETMASK with the mask written in full, and GATEWAY only if there’s a default route).
Expected output, with the workstation configured:
# ./ifcfg-from-live.sh enp2s0 > ifcfg-generated
# cat -n ifcfg-generated
1 DEVICE=enp2s0
2 BOOTPROTO=none
3 ONBOOT=yes
4 IPADDR=10.110.7.4
5 NETMASK=255.255.255.0
6 GATEWAY=10.110.7.1
ip -br -4 addr show dev enp2s0 gives a line whose third column is 10.110.7.4/24. ${cidr%/*} and ${cidr#*/} split it at the slash. To go from 24 to 255.255.255.0, walk through the four bytes subtracting 8 bits each time.
What’s wrong here?
Three snippets on the freshly booted workstation. Before reading the explanation, predict what will come out.
Snippet 1: the IP without a mask
ip link set enp2s0 up ip addr add 10.110.7.4 dev enp2s0 # no /24 ip -br addr ip route ping -c 1 10.110.7.1
Predict: does the gateway reply?
# ip link set enp2s0 up # ip addr add 10.110.7.4 dev enp2s0 # ip -br addr lo UNKNOWN 127.0.0.1/8 enp2s0@if9 UP 10.110.7.4/32 # ip route # ping -c 1 10.110.7.1 ping: connect: Network is unreachable # ip addr del 10.110.7.4/32 dev enp2s0 # ip addr add 10.110.7.4/24 dev enp2s0 # ping -c 1 10.110.7.1 PING 10.110.7.1 (10.110.7.1) 56(84) bytes of data. 64 bytes from 10.110.7.1: icmp_seq=1 ttl=64 time=0.822 ms --- 10.110.7.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.822/0.822/0.822/0.000 ms
Network is unreachable, and ip route is empty. ip -br addr gives it away: 10.110.7.4/32. Without a prefix, ip uses /32, a network of a single address: the workstation itself. As there’s no other address in “its network”, the kernel doesn’t create the 10.110.7.0/24 route, and the gateway .1 is off every known path.
Copying ip addr add 192.168.2.2 dev enp2s0 from a cheat sheet. It works without an error… and leaves the card at /32. Always write the prefix.
The fix is in the last three commands of the session: remove the IP with its /32 (that’s its name now) and set it with /24. The ping replies.
Snippet 2: the card nobody brought up
ip addr add 10.110.7.4/24 dev enp2s0 # IP set correctly… ping -c 1 10.110.7.1 # …but what about the card?
Predict: the IP is set correctly, with its /24. Does the gateway reply?
# ip addr add 10.110.7.4/24 dev enp2s0 # ping -c 1 10.110.7.1 ping: connect: Network is unreachable # ip -br addr lo UNKNOWN 127.0.0.1/8 enp2s0@if13 DOWN 10.110.7.4/24 # ip route # ip link set enp2s0 up # ping -c 1 10.110.7.1 PING 10.110.7.1 (10.110.7.1) 56(84) bytes of data. 64 bytes from 10.110.7.1: icmp_seq=1 ttl=64 time=0.681 ms --- 10.110.7.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.681/0.681/0.681/0.000 ms
No again: Network is unreachable. ip -br addr shows the correct IP next to DOWN, and ip route is empty. A card that’s down has no routes, however well its IP is set. As soon as it’s brought up with ip link set enp2s0 up, the kernel creates the route and the gateway replies.
Faced with Network is unreachable, look at ip -br addr and check two things: UP and the prefix. These are the two most common slips in the lab.
Snippet 3: the router as default gateway
ip link set enp2s0 up ip addr add 10.110.7.4/24 dev enp2s0 ip route add default via 10.110.1.1 # the router's IP as the default gateway
Predict: the router 10.110.1.1 is what gives access to the rest of the lab. Will it do as the default gateway?
# ip link set enp2s0 up # ip addr add 10.110.7.4/24 dev enp2s0 # ip route add default via 10.110.1.1 Error: Nexthop has invalid gateway. # ip route add default via 10.110.7.1 # ping -c 1 10.110.1.1 PING 10.110.1.1 (10.110.1.1) 56(84) bytes of data. 64 bytes from 10.110.1.1: icmp_seq=1 ttl=63 time=0.377 ms --- 10.110.1.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.377/0.377/0.377/0.000 ms
Error: Nexthop has invalid gateway. The default gateway is the first hop and must be on your network, reachable without help. The router is on 10.110.1.0/24, behind the gateway, so the workstation can’t hand it anything directly. With via 10.110.7.1 (the gateway) the route is accepted and the router replies with ttl=63: there was one hop in between.
Before adding a default gateway, run ip route get <gateway IP>: if the answer has via, that IP isn’t on your network and won’t do.
Solutions
Solution to Level 1
# @lab conf ip -br link show enp2s0 # the MAC ip -br addr show enp2s0 # the IP and the prefix ip route show default # the default gateway head -1 /etc/resolv.conf # the first DNS server
Output:
# ip -br link show enp2s0 enp2s0@if21 UP 08:00:27:a1:07:04 <BROADCAST,MULTICAST,UP,LOWER_UP> # ip -br addr show enp2s0 enp2s0@if21 UP 10.110.7.4/24 # ip route show default default via 10.110.7.1 dev enp2s0 # head -1 /etc/resolv.conf nameserver 193.145.147.22
Why it’s done this way:
ip -br link show enp2s0gives the MAC in the third column (08:00:27:a1:07:04), without the extra lines ofip link.ip -br addr show enp2s0gives the IP with prefix on one line:10.110.7.4/24.ip route show defaultfilters just the default route: the third word is the default gateway.head -1 /etc/resolv.conftakes the first line: the DNS server asked first. If the file started with a comment,grep -m1 nameserver /etc/resolv.confwould be safer.
Solution to Level 2
# @lab base ip link set enp2s0 up # ifconfig enp2s0 up ip addr add 10.110.7.5/24 brd + dev enp2s0 # ifconfig enp2s0 10.110.7.5 netmask 255.255.255.0 broadcast 10.110.7.255 ip route add default via 10.110.7.1 # route add default gw 10.110.7.1 ip addr show enp2s0 route -n # check with the old command ping -c 2 10.110.1.1
Output:
# ip link set enp2s0 up
# ip addr add 10.110.7.5/24 brd + dev enp2s0
# ip route add default via 10.110.7.1
# ip addr show enp2s0
26: enp2s0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 08:00:27:a1:07:04 brd ff:ff:ff:ff:ff:ff link-netns gateway
inet 10.110.7.5/24 brd 10.110.7.255 scope global enp2s0
valid_lft forever preferred_lft forever
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.110.7.1 0.0.0.0 UG 0 0 0 enp2s0
10.110.7.0 0.0.0.0 255.255.255.0 U 0 0 0 enp2s0
# ping -c 2 10.110.1.1
PING 10.110.1.1 (10.110.1.1) 56(84) bytes of data.
64 bytes from 10.110.1.1: icmp_seq=1 ttl=63 time=0.233 ms
64 bytes from 10.110.1.1: icmp_seq=2 ttl=63 time=0.068 ms
--- 10.110.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1004ms
rtt min/avg/max/mdev = 0.068/0.150/0.233/0.082 ms
Why it’s done this way:
ip link set enp2s0 upis the good oldifconfig enp2s0 up.- IP, mask and broadcast go in one command:
10.110.7.5/24andbrd +. Now theinetline does havebrd 10.110.7.255: the last address of the network (.0to.255, the last is.255). route add default gwbecomesip route add default via.route -nworks as a cross-check: the table has the default route (0.0.0.0towards10.110.7.1, flagsUG: up and via a gateway) and the network route (10.110.7.0, mask255.255.255.0, flagU). Both tools read the same kernel table.- The ping to the router replies 2 of 2 with
ttl=63.
Solution to Level 3
#!/bin/bash
# ifcfg-from-live.sh: writes the ifcfg that would reproduce the configuration the card has NOW
# Usage: ./ifcfg-from-live.sh enp2s0 > ifcfg-generated
dev=$1
cidr=$(ip -br -4 addr show dev "$dev" | awk '{print $3}') # third column: 10.110.7.4/24
ip=${cidr%/*} # what comes before the slash
p=${cidr#*/} # what comes after the slash
gw=$(ip route show default | awk '{print $3}') # "default via 10.110.7.1 dev …": third word
mask() { # 24 -> 255.255.255.0: four bytes, each with up to 8 bits set
local p=$1 m="" i b
for i in 1 2 3 4; do
if [ "$p" -ge 8 ]; then b=255; p=$((p - 8)) # full byte
else b=$((256 - 2 ** (8 - p))); p=0 # partial byte (or 0 if no bits are left)
fi
m="$m$b"; [ $i -lt 4 ] && m="$m."
done
echo "$m"
}
echo "DEVICE=$dev"
echo "BOOTPROTO=none"
echo "ONBOOT=yes"
echo "IPADDR=$ip"
echo "NETMASK=$(mask "$p")"
[ -n "$gw" ] && echo "GATEWAY=$gw" # with no default route, the line isn't written
The session:
# @lab conf ./ifcfg-from-live.sh enp2s0 > ifcfg-generated cat -n ifcfg-generated
Output:
# ./ifcfg-from-live.sh enp2s0 > ifcfg-generated
# cat -n ifcfg-generated
1 DEVICE=enp2s0
2 BOOTPROTO=none
3 ONBOOT=yes
4 IPADDR=10.110.7.4
5 NETMASK=255.255.255.0
6 GATEWAY=10.110.7.1
Why it’s done this way:
-4limits the output to IPv4 and-brkeeps it on one line:enp2s0@if… UP 10.110.7.4/24.awk '{print $3}'takes the third column. That way the script doesn’t depend on how many spacesipputs between columns.${cidr%/*}removes from the last slash to the end (leaving the IP) and${cidr#*/}removes up to the first slash (leaving the prefix).ip route show defaultgivesdefault via 10.110.7.1 dev enp2s0: the third word is the default gateway. If there’s no default route,gwstays empty and the last line doesn’t writeGATEWAY.- The script prints; the
> ifcfg-generatedredirection decides where it’s saved. That way you can review the result before copying it to/etc/sysconfig/network-scripts/.
The mask function is the inverse of the practice’s prefix. Trace with p=24:
mask() { # 24 -> 255.255.255.0: four bytes, each with up to 8 bits set
local p=$1 m="" i b
for i in 1 2 3 4; do
if [ "$p" -ge 8 ]; then b=255; p=$((p - 8)) # full byte
else b=$((256 - 2 ** (8 - p))); p=0 # partial byte (or 0 if no bits are left)
fi
m="$m$b"; [ $i -lt 4 ] && m="$m."
done
echo "$m"
}
Loop i | p on entry | p ≥ 8? | b | p on exit | m |
|---|---|---|---|---|---|
| 1 | 24 | yes | 255 | 16 | 255. |
| 2 | 16 | yes | 255 | 8 | 255.255. |
| 3 | 8 | yes | 255 | 0 | 255.255.255. |
| 4 | 0 | no | 256 − 2⁸ = 0 | 0 | 255.255.255.0 |
With a prefix like 26, the fourth loop would give 256 − 2^(8−2) = 256 − 64 = 192: 255.255.255.192. The [ $i -lt 4 ] check avoids a dot after the last byte.
Try it in your terminal
ip route get is the best way to understand routes: you give it a destination and it tells you what the kernel would do, without sending anything. It doesn’t need root. As a normal user on the workstation:
# @lab conf # @sergio ip route get 10.110.7.1 # on my network: direct ip route get 10.110.1.1 # off my network: via the gateway ip route get 127.0.0.1 # myself
The real session:
$ ip route get 10.110.7.1
10.110.7.1 dev enp2s0 src 10.110.7.4 uid 1001
cache
$ ip route get 10.110.1.1
10.110.1.1 via 10.110.7.1 dev enp2s0 src 10.110.7.4 uid 1001
cache
$ ip route get 127.0.0.1
local 127.0.0.1 dev lo src 127.0.0.1 uid 1001
cache <local>
What to watch for:
- For
10.110.7.1(the gateway) there’s novia: it’s on my network and is delivered directly throughenp2s0. - For
10.110.1.1,via 10.110.7.1appears: it isn’t on my network, so it goes to the default gateway. src 10.110.7.4is the IP the packet would leave with: the chosen card’s.127.0.0.1goes throughloand islocal: it never leaves the machine.- On your computer, try
ip route get 8.8.8.8: you’ll see your default gateway and which card you use to reach the internet (wlp…if you’re on wifi).
Cheat sheet: network configuration
The essentials in 30 seconds
Getting a network takes three things: the card up, an IP with a prefix (/24 = 255.255.255.0) and a default gateway inside your network. With ip you configure it on the spot (and it’s lost on reboot); with the ifcfg and ONBOOT=yes it sticks. DNS servers go in /etc/resolv.conf.
Looking
| I want to… | Command | Result |
|---|---|---|
| summary of cards and IPs | ip -br addr | enp2s0 UP 10.110.7.4/24 |
| the MAC | ip -br link | 08:00:27:a1:07:04 |
| the routing table | ip route (or route -n) | default via 10.110.7.1 dev enp2s0 |
| which path a packet takes | ip route get 10.110.1.1 | via 10.110.7.1 dev enp2s0 src 10.110.7.4 |
| learnt MACs (ARP) | ip neigh | 10.110.7.1 … lladdr … REACHABLE |
| the DNS servers | cat /etc/resolv.conf | nameserver 193.145.147.22 |
Configuring on the spot (as root)
| I want to… | Command | Result |
|---|---|---|
| bring the card up | ip link set enp2s0 up | UP,LOWER_UP |
| set IP and broadcast | ip addr add 10.110.7.4/24 brd + dev enp2s0 | 10.110.7.0/24 route created automatically |
| default gateway | ip route add default via 10.110.7.1 | |
| remove one IP / all of them | ip addr del 10.110.7.4/24 dev enp2s0 / ip addr flush dev enp2s0 | their routes go too |
| remove the default gateway | ip route del default | |
| test | ping -c 3 10.110.7.1 | ttl=64 on your network, 63 after one router |
Permanent
| File | Contents |
|---|---|
/etc/sysconfig/network-scripts/ifcfg-enp2s0 | DEVICE, BOOTPROTO=none, ONBOOT=yes, IPADDR, NETMASK, GATEWAY |
/etc/resolv.conf | nameserver IP (one per line) |
| apply | systemctl restart network (with NetworkManager stopped: systemctl stop NetworkManager) |
Exercise templates
| Exercise | Key commands | Result |
|---|---|---|
| Level 1 | ip -br link show X, ip -br addr show X, ip route show default, head -1 /etc/resolv.conf | MAC, IP/prefix, gateway, DNS |
| Level 2 | ip link set X up; ip addr add IP/24 brd + dev X; ip route add default via GW | brd 10.110.7.255, ping with ttl=63 |
| Level 3 | ip -br -4 addr show dev X | awk '{print $3}', ${cidr%/*}, ${cidr#*/}, mask function | a 6-line ifcfg |
Symptom / likely cause
| Symptom | Likely cause |
|---|---|
connect: Network is unreachable | card DOWN, IP without prefix (/32) or default gateway missing |
Destination Host Unreachable | there’s a route, but the destination or the gateway doesn’t answer on the local network (an IP from another network?) |
Error: Nexthop has invalid gateway. | the default gateway isn’t on your network |
RTNETLINK answers: Operation not permitted | you’re not root: sudo |
Error: ipv4: Address already assigned. / RTNETLINK answers: File exists | that IP / that route was already set |
| everything is lost on reboot | you configured it with ip; move it to the ifcfg with ONBOOT=yes |
Before you hand it in, ask yourself
- Have I pinged something on my network and something outside it?
- Do all the IPs have their prefix?
- Is the default gateway on my network (
ip route getwith novia)? - Is whatever must survive a reboot in the
ifcfgwithONBOOT=yes?
This topic ends the practical Linux part of IC2. Next comes the theory that explains everything you’ve just configured: how networks work on the inside.
Keep goingAll Linux articlesDid this article help you? Here is how you can support SergioLearns →




What is an operating system — theory with your laptop on a study afternoon, a write() call and a CPU that never rests (and the three programs that weren’t running at the same time)