/etc
make-kpkg
to compile a Linux kernel (Debian)ip6tables
)/etc
I did the following on many of the various machines which I
administrate: as root, go in /etc
and run (umask
077 ; git init-db)
; then periodically (e.g., with a crontab)
run the following script (again, as root):
#! /bin/sh if [ "x$1" = "x" ]; then log_message="autocommit" else log_message="$1" fi cd /etc # Keep a list of installed packages (this is Debian-specific) COLUMNS=160 dpkg -l > 00PACKAGES # Also keep a list of all files present, with full metadata find /etc \( -name .git -o -name 00FILES \) -prune -o -print \ | sort | xargs stat -c '%A %5h %6u %6g %12s %y %n' > 00FILES # Make sure all files are in index git ls-files -c -d -o -z | git update-index --add --remove -z --stdin git commit -m "$log_message" -n # Not sure the following is really a good idea... git repack -d
Example uses:
git whatchanged -p X11/xorg.conf
git diff @{2007-09-01} master -- 00FILES
git cat-file -p @{2007-09-01}:passwd
passwd
file as it stood on 2007-09-01To send to a remote machine for backup, use git
init-db
on some /directory
and then run
git push ssh://remote.machine/directory/
refs/heads/master:refs/heads/here
(where
here is the branch name to be used to identify the local
machine). Conversely, one can fetch the local files on the remote
machine with git fetch here
provided
.git/remotes
was created containing:
URL: ssh://local.machine/etc/ Pull: refs/heads/master:refs/heads/here
make-kpkg
to compile a Linux kernel (Debian)Extract kernel in
/usr/src/linux-version-local
(e.g.,
/usr/src/linux-2.6.17.11-machinename
with all
appropriate patches. Copy some config file to .config
(usually starting from the previous version).
YYYYMMDD="`date +%Y%m%d`" make-kpkg --revision=custom.$YYYYMMDD --append-to-version=-local \ --config oldconfig configure
(or use menuconfig
if preferred)… Edit
debian/control
(change maintainer) and
debian/changelog
(wipe and restart with previously
compiled version as template; be sure to preserve the first line,
however! it contains the version number).
MAKEFLAGS="CC=gcc-4.0" CONCURRENCY_LEVEL="2" make-kpkg \ --revision=custom.$YYYYMMDD --append-to-version=-local \ --rootcmd fakeroot kernel_image kernel_headers
(Of course, I use CONCURRENCY_LEVEL="2"
because I have
a dual-core proc.)
Make sure the linux-headers-version
package
is installed so that /lib/modules/`uname -r`/build
points
to the right place. Then from the directory containing the module to
be built:
make -C /lib/modules/`uname -r`/build CC="gcc-4.0" M=`pwd`
(the gcc
version must match that used to compile the
kernel itself, of course; if in doubt, use modinfo
).
To be asked the signature level when signing, add the
(undocumented?) --ask-cert-level
option along with
--edit-key
(used to be default, but it was thought to be
too confusing).
To set preferences for hash algorithms &c., use
--edit-key
and then something like
setpref s10 s9 s8 s7 s3 s4 s2 h8 h10 h9 h11 h3 h2 z2 z3 z1 z0
(that's my preference: h8
means sha256
and so on; maybe now they can be entered with more user-friendly
names?).
Note on choice of cipher and hash: GnuPG chooses the
cipher and hash functions according to the preferences in the
recipient's self-signature (see above) and also the
personal-cipher-preferences
and
personal-hash-preferences
(on the command line or in
.gnupg/options
), but not beyond what the recipient
authorizes. One can manually override with --cipher-algo
and --digest-algo
. But it's probably not a good idea.
(The same holds for the compression functions.)
Note on DSA2: Currently (version 1.4.5),
GnuPG prefers, if it is possible (that is, if the key
allows) to use the old DSA standard, which limits
DSA keys to 1024 bits and hash functions to 160 bits.
The new DSA2 standard, which is not well supported
outside GnuPG, must be explicitly requested using
enable-dsa2
(on the command line or in the config file).
One can also explicitly request a larger hash function, e.g.,
using --digest-algo SHA256
.
Note about GnuPG v2: Currently it has no support
for SHA224 (that's a bit odd). It will get it in
the libgcrypt
stable version 1.4.x (currently
it
is in
the unstable version 1.3.x). The following signature
currently cannot be decoded with GnuPG v2:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA224 It would seem that GnuPG2 does not have the SHA224 digest algo! -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFG68GLDZNkJgsnkN4RC4MAAKCsuSnydZSzLQfl/rf6WcoZpUczOgCfXsmC yiS5H8EOb5BnH2DLmWXuz38= =cSjt -----END PGP SIGNATURE-----
[Originally published in my blog.]
This took me a while to figure out, so I might as well post it here
in case it's of use to anyone. Assume you have two network
interfaces, say eth0
and ppp0
, with two
totally unrelated IP addresses, say
257.42.0.18
for eth0
(yes, I know, 257 is
impossible, I'm just choosing this to represent a totally arbitrary
address) and 333.64.17.29
for ppp0
. You
wish to use one interface for certain connections and the other for
others (there can be plenty of different reasons for that: maybe one
connection is faster but has a stupid firewall so it can't be used
always). Now if you can decide which connection goes where in
function of the destination host('s IP address or
network), then it's easy: just configure your routing tables
appropriately. But what happens if you wish, for example, all
outbound connections to TCP port 80 to go through
eth0
and all others to go through ppp0
? We
need a little more work there, and a little magic, but thanks to the
mutant features of the Linux network stack, using
iptables
and iproute2
, it is possible.
Here's a sample of the command lines that might be useful (just a
guideline, of course: don't ever copy them blindly, please learn about
the programs and understand what each line does), at least if the host
is not a router:
# Ordinary route is via ppp0 (this should probably be done as pppd starts): route add defaut gw 333.64.17.1 dev ppp0 # Routing table 201 (say) is through eth0 (gateway is 257.42.0.1, say): ip route add 257.42.0.0/24 dev eth0 scope link src 257.42.0.18 table 201 ip route add default via 257.42.0.1 dev eth0 table 201 # Use routing table 201 for marked packets: ip rule add fwmark 1 table 201 # Now set up iptable rule to mark packets destined for eth0: iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 80 -j MARK --set-mark 1 # Lastly, we need to do some self-masquerading: iptables -t nat -A POSTROUTING -s 333.64.17.29 -o eth0 -j SNAT --to-source 257.42.0.18
The last line probably deserves extra comments, because it is not
at all obvious: it is needed because otherwise an outbound connection
from the local host on port 80 will have local address
333.64.17.29
(as it appears on the ordinary routing
table) whereas it is sent through the eth0
device, and
this can't work (any router down the stream will reject it as not
being meant for this route, or at best the return packets will come
through the wrong interface).
If you're also trying to open listening (server) sockets on the
eth0
interface, you also need something probably like
this:
# Turn off entry route verification on incoming packets: sysctl -w net.ipv4.conf.eth0.rp_filter=0 # Also mark local packets destined for eth0: iptables -t mangle -A OUTPUT -s 257.42.0.18 -j MARK --set-mark 1
If your box also acts as a router (through some third interface
eth1
, say), then at the very least you need to duplicate
the OUTPUT
rules (for the mangle
table) as
PREROUTING
ones and broaden the source address match on
the rules that have one, but more complicated are probably desirable
(of course, it all depends on what kind of addresses you have on
eth1
; I'll leave as an exercise for the interested reader
the case where eth1
has private addresses and you wish to
masquerade on forwarding…).
ip6tables
)No longer needed! There is now
an xtables
implementation of TCPMSS
, which
works both with IPv4 and
with IPv6: CONFIG_NETFILTER_XT_TARGET_TCPMSS
(module name xt_TCPMSS
).
2007-01-14: Shamelessly copying Marc Boucher's implementation
for IPv4, I wrote a TCPMSS
target for
ip6tables
(Marc's original implementation for
iptables
is now a standard part of the kernel and
iptables
). Both the kernel patch (creating the
ip6t_TCPMSS.ko
module) and the accompanying
iptables
patch can be downloaded from my
FTP site.
ECC memory does its task without any software support (provided it is enabled in the BIOS, something one tends to forget about, and provided the chipset supports it, of course!). However, it's nice to be able to query the status in software so as to learn about which errors have been corrected or detected.
The following simple script checks the ECC status on
two Intel northbridges which I happen to have, namely the [82]975X
(e.g., on the Asus P5W64 WS Pro motherboard), the 82955X (part of the
955X chipset, e.g., on the Asus P5WD2 Premium motherboard), and the
older 82845 (part of the 845E chipset, e.g., on the Asus P4B533
motherboard). If you have a different but similar Intel chipset, you
can probably hack a simple patch by comparing the Intel datasheet for
your chipset (look for registers with names like ERRSTS
and EAP
) with that of the aforementioned two
(see here
for the [82]975X,
here
for the 82955X
and here
for the 82845); note that ID 0x277c8086
refers to the [82]975X, 0x27748086
to the 82955X
and 0x1a308086
to the 82845.
#! /usr/local/bin/perl -w # ecccheck.pl -- Check ECC status on the Intel 82845, 82955X and [82]975X. # David Madore <david.madore@ens.fr> -- 2007-09-19 -- Public Domain # Updated 2007-10-03 to add support for the 975X. use strict; use warnings; use English '-no_match_vars'; use Getopt::Std; use Sys::Syslog qw(:standard :macros); die "must be run as root" if $EFFECTIVE_USER_ID; my %opts; # -c (clear): ignore reported ECC errors (use this once at boot, to reset) # -r (read): read reported ECC errors without clearing them (just test) # Normal use: once with -c at boot, then periodically without options. getopts("cr", \%opts); # Northbridge is supposed to be device 0 function 0 on PCI bus 0. my $conf_file = "/sys/bus/pci/devices/0000:00:00.0/config"; sub readconf { # Read PCI configuration variable. # Force a reopen of the file, so no buffering will be done by Perl/libc. open F, "<", $conf_file; my $off = shift; my $len = shift; seek F, $off, 0; my $buf; read F, $buf, $len; close F; return $buf; } sub writeconf { # Write PCI configuration variable. open F, "+<", $conf_file; my $off = shift; my $data = shift; seek F, $off, 0; print F $data; close F; } my $id = unpack ("V", readconf(0, 4)); # 0x27748086 is the 82955X and 0x1a308086 is the 82845 # 0x277c8086 is the 975X unless ( $id == 0x277c8086 || $id == 0x27748086 || $id == 0x1a308086 ) { die "unknown northbridge"; } if ( $id == 0x1a308086 && ( unpack("V", readconf(0x7c, 4)) & 0x300000 ) != 0x200000 ) { die "ECC disabled (or unknown mode)"; } my $retcode = 0; my $type; my $pos; my $chan; my $syn; while (1) { $type = unpack ("C", readconf(0xc8, 1)) & 3; exit 0 unless $type; if ( $id == 0x277c8086 || $id == 0x27748086 ) { my $v = unpack ("V", readconf(0x58, 4)); # Error address $pos = ($v & 0xffffff80) || ((unpack ("C", readconf(0xfc, 1)) & 1) << 32); $chan = $v & 1; # Error syndrome $syn = unpack ("C", readconf(0x5c, 1)); } elsif ( $id == 0x1a308086 ) { # Error address $pos = (unpack ("V", readconf(0x8c, 4)) & 0x3ffffffe) << 2; # Error syndrome $syn = unpack ("C", readconf(0x86, 1)); } # If the type has changed, reread values to prevent race-condition. my $type2 = unpack ("C", readconf(0xc8, 1)) & 3; last if $type2 == $type; } unless ( $opts{"r"} ) { # Clear the type bits we have just read (notice that there is no race here!). writeconf(0xc8, pack("C", $type)); } if ( $type && ! $opts{"c"} ) { openlog("ecccheck.pl", 0, LOG_LOCAL0); sub printf_log { my $priority = shift; my $format = shift; my @args = @_; syslog $priority, $format, @args; printf $format, @args; } my $prio = ($type&2)?LOG_CRIT:LOG_ERR; printf_log LOG_ERR, "single-bit (corrected) ECC error\n" if $type & 1; printf_log LOG_CRIT, "MULTIPLE-bit (uncorrectable) ECC error\n" if $type & 2; printf_log $prio, "address: 0x%010x\n", $pos if defined($pos); printf_log $prio, "channel: %d\n", $chan if defined($chan); printf_log $prio, "syndrome: 0x%02x\n", $syn if defined($syn); closelog; exit 1; }
To use this, simply run it—as root—once at boot time
with -c
as argument (to clear the ECC error
flags) and then periodically (every 5 minutes, say) without arguments;
the simplest is probably to use a crontab (so any error messages get
sent by email). Nothing is printed in case of success (and it returns
with error code 0
).
Important note: If you use ECC, make
sure to disable any quick boot
(or similarly named)
option in your BIOS. Otherwise your memory will
not be initialized at boot and you will get loads of ECC
errors (mostly at the top of available RAM, it
seems) from unclean ECC bits. I had a hart time figuring
this one out.
This is not directly Linux-related, but still useful: sometimes one needs to boot under DOS, typically to flash a firmware or something of the sort. FreeDOS can be used, but installing so as to make a USB stick (thumb drive) bootable isn't easy, and the following instructions are hard to find:
makebootfat
, nasm
and SysLinux;freedos/packages/base/kernelx.zip
from the CD, take the
file source/sys37/boot/boot32lb.asm
found inside, and
compile it using nasm boot32lb.asm -o fat32lba.bin
: this
will produce the FAT32-LBA boot sector
for FreeDOS 1.1 (I know no other way to get it than
that I've just described: nobody seems to redistribute the
binary);freedos/setup/odin/
found on
the CD somewhere (or use it directly as mounted);makebootfat -v -o /dev/something -E
255 -3 fat32lba.bin -m /usr/lib/syslinux/mbr.bin odin/
where fat32lba.bin
was produced
previously, mbr.bin
comes from
SysLinux, odin/
refers to the directory mentioned above,
and /dev/something
is the device for the
full USB drive (unpartitioned: this will create a
partition table; if one doesn't want to write the partition table,
maybe the -P
option does the appropriate thing, but I
didn't check);/dev/something
(e.g., open it
with fdisk
and quit-and-save with w
;
or sync
, remove and reinsert the stick);msdos
and remove
the fdconfig.sys
file found there.This worked for me. YMMV, of course.